2015-04-16 63 views
2

使用Shell脚本(Bash),我想总结列表中所有不同变量的列。假设我有一个Test.tsv文件的以下输入:多个变量列的总和

  Win Lost 
Anna  1 1 
Charlotte 3 1 
Lauren  5 5 
Lauren  6 3 
Charlotte 3 2 
Charlotte 4 5 
Charlotte 2 5 
Anna  6 4 
Charlotte 2 3 
Lauren  3 6 
Anna  1 2 
Anna  6 2 
Lauren  2 1 
Lauren  5 5 
Lauren  6 6 
Charlotte 1 3 
Anna  1 4 

我想总结每个参与者赢得和失去了多少。所以我想得到这个结果:

  Sum Win Sum Lost 
Anna  57   58 
Charlotte 56   57 
Lauren  53   56 

我通常会做的是采取每人和每列的总和,并重复该过程一遍又一遍。请参阅下面我将如何处理上述示例:

cat Test.tsv | grep -Pi '\bAnna\b' | cut -f2 -d$'\t' |paste -sd+ | bc > Output.tsv 
cat Test.tsv | grep -Pi '\bCharlotte\b' | cut -f2 -d$'\t' |paste -sd+ | bc >> Output.tsv 
cat Test.tsv | grep -Pi '\bLauren\b' | cut -f2 -d$'\t' |paste -sd+ | bc >> Output.tsv 
cat Test.tsv | grep -Pi '\bAnna\b' | cut -f3 -d$'\t' |paste -sd+ | bc > Output.tsv 
cat Test.tsv | grep -Pi '\bCharlotte\b' | cut -f3 -d$'\t' |paste -sd+ | bc >> Output.tsv 
cat Test.tsv | grep -Pi '\bLauren\b' | cut -f3 -d$'\t' |paste -sd+ | bc >> Output.tsv 

但是我需要为每个参与者重复此行。当你需要对许多变量进行总结时,这会变得很痛苦。

写这个脚本的方法是什么?

谢谢!

回答

6

awk很简单。使用GNU AWK:

awk -F '\t' 'BEGIN { OFS = FS } NR > 1 { won[$1] += $2; lost[$1] += $3 } END { PROCINFO["sorted_in"] = "@ind_str_asc"; print "", "Sum Win", "Sum Lost"; for(p in won) print p, won[p], lost[p] }' filename 

-F '\t'使得awk的分割线的标签,然后:

BEGIN { OFS = FS } # the output should be separated the same way as the input 

NR > 1 {   # From the second line forward (skip header) 
    won[$1] += $2  # tally up totals 
    lost[$1] += $3 
} 

END {    # When done, print the lot. 

    # GNU-specific: Sorted traversal or player names 
    PROCINFO["sorted_in"] = "@ind_str_asc" 

    print "", "Sum Win", "Sum Lost" 
    for(p in won) print p, won[p], lost[p] 
} 
+0

这岂不是更容易只使用ASORT? –

+0

你可以使用'asorti',但是因为这也是GNU特有的,所以它没有太大区别。如果没有GNU awk,我可能会将标题从awk输出中删除,通过'sort'打印未排序的管道,然后添加标题。 – Wintermute