【问题标题】:Script to sum columns in multiple files对多个文件中的列求和的脚本
【发布时间】:2019-02-12 13:28:34
【问题描述】:
File A
Sector A    100
Sector B    200
Sector C    300
Sector D    500


File B
Sector A    100
Sector B    200
Sector C    300
Sector D    500


File C
Sector A    100
Sector B    200
Sector C    300
Sector D    500

我想获得一个文件,其中包含所有文件的扇区 A、B、C 的总和。

最终结果

Sector A    300
Sector B    600
Sector C    900
Sector D    1500

Shell 脚本会很棒!!!感谢您的建议。

【问题讨论】:

  • 你试过什么? PS:也许你的意思是“Sector D 1500”
  • 如果此处的答案之一解决了您的问题,请接受该答案。接受答案会关闭此问题并奖励接受答案的作者。如果您的问题没有得到解决,请考虑解释原因。

标签: bash shell awk scripting


【解决方案1】:

请您尝试关注一下。

awk '{a[$1 FS $2]+=$NF} END{for(i in a){print i,a[i]}}' fileA fileB fileC

输出如下。

Sector A 300
Sector B 600
Sector C 900
Sector D 1500

【讨论】:

  • 你好拉文德,
  • 非常感谢您的回答。我是脚本新手,请您写下步骤。这将有助于更快地学习。另外,我有多个文件,我可以在命令末尾使用通配符 (*)
【解决方案2】:

假设您的列由制表符分隔,您可以使用 GNU datamash:

sort fileA fileB fileC | datamash groupby 1 sum 2

输出

Sector A    300
Sector B    600
Sector C    900
Sector D    1500

如果您的(可能很大)单个输入文件已经排序,您可以使用sort -m ... 而不是sort 来加快处理过程。

【讨论】:

  • 如果-W被任意空格分隔,则添加。
  • @Shawn 不幸的是,这并不容易。 Sector A 也包含一个空格。如果您知道第一列总是包含一个空格(对于 OP 的示例输入),那么我们可以使用datamash -W groupby 1,2 sum 3。如果第一个“列”可以是任何东西,那么我们就迷路了,但这是一个普遍的问题不是特定于datamash
【解决方案3】:

不是最聪明的解决方案,但非常简单易懂:

for f in fileA fileB fileC
do
   while read line
   do
   A=$(echo $line | grep "Sector A" | tr -s " "| cut -d' ' -f3)
   B=$(echo $line | grep "Sector B" | tr -s " "| cut -d' ' -f3)
   C=$(echo $line | grep "Sector C" | tr -s " "| cut -d' ' -f3)
   D=$(echo $line | grep "Sector D" | tr -s " "| cut -d' ' -f3)
   secA=$((secA+A))
   secB=$((secB+B))
   secC=$((secC+C))
   secD=$((secD+D))
   done < $f
done
echo "Sector A" $secA
echo "Sector B" $secB
echo "Sector C" $secC
echo "Sector D" $secD

【讨论】:

    【解决方案4】:

    使用 Perl,

    $ perl -0777 -ne ' s/^(.+) (\d+)$/$kv{$1}+=$2/gme; END { for(sort keys %kv) { print "$_ $kv{$_}\n" }} ' filea.txt fileb.txt  filec.txt
    Sector A    300
    Sector B    600
    Sector C    900
    Sector D    1500
    $
    

    【讨论】:

      【解决方案5】:

      1.sort协助awk

      $  sort filea.txt fileb.txt  filec.txt | awk ' { c=$2; if(c!=p && NR>1 ) { print $1,p,s;s=0} p=c;s+=$3 } END { print $1,p,s } '
      Sector A 300
      Sector B 600
      Sector C 900
      Sector D 1500
      $
      

      2.paste协助awk

      $ paste filea.txt fileb.txt  filec.txt | awk ' { for(i=3;i<=NF;i+=3) s+=$i; print $1,$2,s ; s=0 } '
      Sector A 300
      Sector B 600
      Sector C 900
      Sector D 1500
      $
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-02-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-14
        • 1970-01-01
        相关资源
        最近更新 更多