在行Bash上添加变量

时间:2015-03-15 23:58:27

标签: bash file addition

我有一个这样的文件:

Dave 10 20 55
Kate 17 12 1 399
Simon 9 209 1 55 5
Charles 1 2

如何逐行为每个人添加这些数字,它还适用于不同数量的数字?

所以输出会是这样的:

Dave 85
Kate 429
etc.

任何方向都将不胜感激!

5 个答案:

答案 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,trbc(假设您的文件名为numbers.txt):

#!/bin/bash

while read name numbers
do
  echo -n "${name} "
  tr " " "+" <<< "$numbers" | bc
done < numbers.txt

每一行分为namenumbers。打印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