我有一个包含多行和两或四列的文本文件。如果两列,则第一列为id,第二列为数字,如果四列第一和第二列为id,第三列和第四列为数字。对于四列行,第二和第四列单元格可以有多个条目,并用逗号分隔。如果只有两栏,我想按原样打印;但是如果有四列,我只想打印第一列ID,在第二列中,我想要该行的第三列和第四列中存在的所有数字的总和。
CG AT,AA,CA 17 1,1,1
GT 14
TB AC,TC,TA,GG,TT,AR,NN,NM,AB,AT,TT,TC,CA,BB,GT,AT,XT,MT,NA,TT 552 6,1,1,2,2,1,2,1,5,3,4,1,2,1,1,1,3,4,5,4
TT CG,GT,TA,GB 105 3,4,1,3
CG 20
GT 14
TB 602
TT 116
答案 0 :(得分:3)
如果实际文件中没有前导空格,请使用$1
而不是$2
。
$ awk -F '[ ,]+' '{for(i=1; i<=NF; i++) s+=$i; print $2, s; s=0}' <<EOF
CG AT,AA,CA 17 1,1,1
GT 14
TB AC,TC,TA,GG,TT,AR,NN,NM,AB,AT,TT,TC,CA,BB,GT,AT,XT,MT,NA,TT 552 6,1,1,2,2,1,2,1,5,3,4,1,2,1,1,1,3,4,5,4
TT CG,GT,TA,GB 105 3,4,1,3
EOF
CG 20
GT 14
TB 602
TT 116
-F '[ ,]+'
表示“字段由一个或多个空格或逗号分隔”。
没有与{action}
关联的条件,因此将在每一行上执行。
NF
是字段数,而$X
是第X个字段。
字符串等于0,因此我们可以简单地将每个字段加在一起以获得总和。
在打印第一个非空白字段和总和之后,我们将下一行的总和重置。
答案 1 :(得分:1)
这是一个编码为尽可能接近您的说明的解决方案(没有用于拆分字段的技巧,因此很容易推理):
awk '
NF == 2 {
print $1, $2
next
}
NF == 4 {
N = split($4, f, /,/)
for (i = 1; i <= N; ++i)
$3 += f[i]
print $1, $3
}'
我注意到您的输入部分包含前导空格。如果前导空格确实存在(并且不相关),我们可以在脚本中添加前导{ sub(/^ +/, "") }
。