使用'line'在UNIX中逐行读取文件的内容

Jus*_*tin 1 unix bash shell

我有一个文件abc,其内容如下:

Bob 23  
Jack 44  
Rahul 36 
Run Code Online (Sandbox Code Playgroud)

我也有一个shell脚本,可以在这里添加所有数字。选取这些数字的特定行是-

while read line  
do  
    num=echo ${line#* }  
    sum=`expr $sum + $num`  
    count=`expr $count + 1`  
done< "$readfile"  
Run Code Online (Sandbox Code Playgroud)

我以为代码只是从文件中获取最后一个字段,但事实并非如此。如果我像修改文件

Bob 23 12  
Jack 44 23  
Rahul 36 34 
Run Code Online (Sandbox Code Playgroud)

同一脚本因语法错误而失败。

注意:我知道还有其他获取字段值的方法,但是我想知道这是如何工作的。

Ini*_*ian 5

The syntax ${line#* } will skip the shortest string from the beginning till it finds a space and returns the rest. It worked fine when you had just 2 columns. But the same will not work when 3 columns are present as it will return you the last 2 column values which when you use it in the sum operator will throw you an error. To explain that, just imagine

str='foo bar'
printf '%s\n' "${str#* }"
bar
Run Code Online (Sandbox Code Playgroud)

but imagine the same for 3 fields

str='foo bar foobar'
printf '%s\n' "${str#* }"
bar foobar
Run Code Online (Sandbox Code Playgroud)

To fix that use the parameter expansion syntax of "${str##* }" to skip the longest sub-string from beginning. To fix your script for the example with 3 columns, I would use a script as below.

This does a simple input redirection on the file and uses the read command with the default IFS value which is a single white space. So I'm getting only the 3rd field on each line (even if it has multiple fields), the _ mark the fields I'm skipping. You could also have some variables as place-holders and use their value in the scripts also.

declare -i sum

while read -r _ _ value _ ; do
    ((sum+=value)
done < file

printf '%d\n' "$sum"
Run Code Online (Sandbox Code Playgroud)

See Bash - Parameter Expansion (Substring removal) to understand more.

You could also use the PE syntax ${line##* } as below,

str='foo bar'
printf '%s\n' "${str#* }"
bar
Run Code Online (Sandbox Code Playgroud)

[Not relevant to the current question]

If you just want the sum to be computed and not specifically worried about using bash script for this. You can use a simple Awk command to sum up values in 3rd column as

awk '{sum+=$3}END{print sum}' inputfile
Run Code Online (Sandbox Code Playgroud)