我有一个这样的文件:
Dave 10 20 55
Kate 17 12 1 399
Simon 9 209 1 55 5
Charles 1 2
如何逐行为每个人添加这些数字,它还适用于不同数量的数字?
所以输出会是这样的:
Dave 85
Kate 429
etc.
任何方向都将不胜感激!
答案 0 :(得分:2)
我想添加一个仅限Bash的解决方案:
while read a b ; do echo "${a} "$(( ${b// /+} )) ; done < numbers.txt
或,扩展:
#!/bin/bash
while read name numbers
do
echo -n "${name} "
echo $(( ${numbers// /+} ))
done < numbers.txt
这在参数扩展期间使用Bash的模式替换来替换空白+
,并使用算术扩展来计算总和。
答案 1 :(得分:1)
这种任务就是AWK真正的目标。
以下脚本 - 针对可读性而非最小字符数进行了优化 - 可以满足您的要求。
/^[[:alpha:]]+([[:space:]]+[[:digit:]]+)*[[:space:]]*$/ {
name = $1;
sum = 0;
for (i = 2; i <= NF; ++i) {
sum += $i;
}
printf("%s %d\n", name, sum);
}
如果您将脚本保存为script.awk
并且您的数据位于名为data.txt
的文件中,则可以运行awk -f script.awk data.txt
并将结果写入标准输出。
如果您了解AWK的基础知识,上述脚本中的逻辑非常简单。如果你不这样做,我建议你阅读The GNU Awk User’s Guide。简而言之:^[[:alpha:]]+([[:space:]]+[[:digit:]]+)*[[:space:]]*$
是一个正则表达式(using POSIX character classes),它匹配一个名称后跟零个或多个数字。如果该模式匹配,则激活规则并迭代记录中除第一个字段之外的所有字段,将它们相加。最后,结果通过熟悉的printf
打印出来。
如果要编写单个shell脚本,可以像这样内联AWK脚本:
awk '
# Here goes the AWK script...
# It cannot contain a single quote in this case.
' data.txt
答案 2 :(得分:1)
这是一个Awk程序。 Awk会自动遍历文件中的所有行。我添加了一个内部for
循环来遍历每行中的每个字段。由于每行有不同数量的字段,我使用NF
变量,即每行的字段数。 $1
指的是第一个字段(名称)。 for
从字段#2循环到最后一个字段。使用$num
代替num
是指该字段的值:
awk '{
printf $1 " "
sum = 0
for ( num = 2; num <= NF; num++ ) {
sum += $num
}
print sum
}' file.txt
打印出来:
Dave 85
Kate 429
Simon 279
Charles 3
要让一切都排好,不应该太难。
答案 3 :(得分:0)
这种简单方法使用Bash,tr
和bc
(假设您的文件名为numbers.txt
):
#!/bin/bash
while read name numbers
do
echo -n "${name} "
tr " " "+" <<< "$numbers" | bc
done < numbers.txt
每一行分为name
和numbers
。打印name
后,空格会被+
替换为tr
,然后通过管道传输到bc
来计算该行的总和。
作为一个单行:
while read a b ; do echo -n "${a} " ; tr " " + <<<"$b" | bc ; done < numbers.txt
注意:对于大型输入文件,此解决方案相当慢,因为它每次迭代都会调用多个外部程序。
答案 4 :(得分:0)
awk
非常善于进行此类计算。这是另一个awk解决方案。
$ awk '{for(i=2;i<=NF;i++)a[$1]+=$i}END{for(j in a)print j, a[j]}' input.txt
Charles 3
Dave 85
Simon 279
Kate 429