使用“line”

时间:2017-12-15 07:44:18

标签: bash shell unix

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

Bob 23  
Jack 44  
Rahul 36 

我还有一个shell脚本,可以在这里添加所有数字。 获取这些数字的具体行是 -

while read line  
do  
    num=echo ${line#* }  
    sum=`expr $sum + $num`  
    count=`expr $count + 1`  
done< "$readfile"  

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

那样修改文件
Bob 23 12  
Jack 44 23  
Rahul 36 34 

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

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

1 个答案:

答案 0 :(得分:4)

语法${line#* }将从开头跳过最短的字符串,直到找到空格并返回其余的字符串。只有2列时,它工作正常。但是当存在3列时,的工作方式相同,因为它将返回最后2个列值,当您在sum运算符中使用它时会抛出错误。要解释一下,想象一下

str='foo bar'
printf '%s\n' "${str#* }"
bar

但想象3个字段相同

str='foo bar foobar'
printf '%s\n' "${str#* }"
bar foobar

要解决此问题,请使用"${str##* }"的参数扩展语法从头开始跳过最长的子字符串。要修复包含3列示例的脚本,我将使用如下脚本。

这对文件执行简单的输入重定向,并使用read命令和默认的IFS值,该值是单个空格。因此,我每行只获得第3个字段(即使它有多个字段),_标记我跳过的字段。您也可以将一些变量作为占位符,并在脚本中使用它们的值。

declare -i sum

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

printf '%d\n' "$sum"

请参阅Bash - Parameter Expansion (Substring removal)了解详情。

您也可以使用PE语法${line##* },如下所示

while read -r line ; do
    ((sum+=${line##* }))
done < file

[与当前问题无关]

如果您只想计算总和而不是特别担心使用bash脚本。您可以使用简单的Awk命令将第3列中的值汇总为

awk '{sum+=$3}END{print sum}' inputfile