我有一个带有单词和正数的文本文件,用一些空格分隔,例如
A dog has a ball number 49 number 34 number A
Cats number 58
...
我想总结一下字符串“number”后面出现的所有数字。如果在字符串“number”之后不是数字,则无关紧要。
例如,在这种情况下,答案是49 + 34 + 58,即141
。
答案 0 :(得分:4)
awk '{ for (i = 1; i <= NF; i++) s = s+$i }; END { print s+0 }' test.txt
Awk读取文件,每行一行。对于每一行,执行标记为{}
的块。块可以通过条件来保护:正则表达式,......,以及BEGIN
和END
,它们分别对于第一行和最后一行是“真”。
这意味着awk会为每一行执行第一个块(因为它没有防护)。
此外,awk并没有真正的类型系统 - 所有字符串。但是你可以对字符串使用算术 - 在这种情况下,它们会神奇地转换为数字。如果对不是数字的字符串进行算术运算,则它们会计算为“0”。 这意味着:“asdf”+ 1 = 1; 2 + 4 = 6; “asdf”+ 0 = 0;
不必声明变量 - 默认为空字符串,其数值为'0'。
awk的下一个特色是它会自动将当前输入行拆分为字段。可以指定字段分隔符,但默认为空格。 $1
,$2
,... $NF
可以访问单个字段,即NF
是字段数。 $0
是完整输入行的内容。
你有它:你查看当前行的所有'字段'。所有字段的数值(字符串为0)都在变量s
中累加。阅读完所有内容(END
)后,将打印总和。
修复:
awk '{ for (i = 1; i <= NF; i++) if ($i == "number") {s = s+$(++i)} }; END { print s+0 }' test.txt
这样,它也会产生141输入,如:
10一只狗的球号49号34号A号 猫1000号58
答案 1 :(得分:2)
您可以通过将number
设置为记录分隔符来将输入与awk分开:
awk -v RS=number '{ sum += $1 } END { print sum }' infile
这是一个grep,coreutils和bc替代方案:
(<infile grep -Eoi 'number[[:blank:]]+[0-9]+' \
| tr -s '[:blank:]' | cut -d' ' -f2 | head -c -1 \
| tr '\n' '+'; echo
) | bc
输出:
141