我有一个文件 - 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
相同的脚本因语法错误而失败。
注意:我知道还有其他方法可以获取字段值,但我想知道它是如何工作的。
答案 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