![如何使用 awk 对二维数组中的多个数字求和](https://linux22.com/image/8018/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%20awk%20%E5%AF%B9%E4%BA%8C%E7%BB%B4%E6%95%B0%E7%BB%84%E4%B8%AD%E7%9A%84%E5%A4%9A%E4%B8%AA%E6%95%B0%E5%AD%97%E6%B1%82%E5%92%8C.png)
我需要对文件中的数字进行求和,如下所示:
column1 column2 column3
row1 a(1,1) a(1,2) a(1,3)
row2 a(2,1) a(2,2) a(2,3)
row3 a(3,1) a(3,2) a(3,3)
row4 a(4,1) a(4,2) a(4,3)
row5 a(5,1) a(5,2) a(5,3)
row6 a(6,1) a(6,2) a(6,3)
row7 a(7,1) a(7,2) a(7,3)
row8 a(8,1) a(8,2) a(8,3)
row9 a(9,1) a(9,2) a(9,3)
row10 a(10,1) a(10,2) a(10,3)
row11 a(11,1) a(11,2) a(11,3)
row12 a(12,1) a(12,2) a(12,3)
column4 column5 column6
row1 b(1,1) b(1,2) b(1,3)
row2 b(2,1) b(2,2) b(2,3)
row3 b(3,1) b(3,2) b(3,3)
row4 b(4,1) b(4,2) b(4,3)
row5 b(5,1) b(5,2) b(5,3)
row6 b(6,1) b(6,2) b(6,3)
row7 b(7,1) b(7,2) b(7,3)
row8 b(8,1) b(8,2) b(8,3)
row9 b(9,1) b(9,2) b(9,3)
row10 b(10,1) b(10,2) b(10,3)
row11 b(11,1) b(11,2) b(11,3)
row12 b(12,1) b(12,2) b(12,3)
输出应该是这样的:
column1 a(1,1)+a(2,1)+a(5,1)+a(6,1)+a(7,1)+a(8,1)+a(11,1) a(3,1)+a(4,1)+a(9,1)+a(10,1)+a(12,1)
column2 a(1,2)+a(2,2)+a(5,2)+a(6,2)+a(7,2)+a(8,2)+a(11,2) a(3,2)+a(4,2)+a(9,2)+a(10,2)+a(12,2)
column3 a(1,3)+a(2,3)+a(5,3)+a(6,3)+a(7,3)+a(8,3)+a(11,3) a(3,3)+a(4,3)+a(9,3)+a(10,3)+a(12,3)
column4 b(1,1)+b(2,1)+b(5,1)+b(6,1)+b(7,1)+b(8,1)+b(11,1) b(3,1)+b(4,1)+b(9,1)+b(10,1)+b(12,1)
column5 b(1,2)+b(2,2)+b(5,2)+b(6,2)+b(7,2)+b(8,2)+b(11,2) b(3,2)+b(4,2)+b(9,2)+b(10,2)+b(12,2)
column6 b(1,3)+b(2,3)+b(5,3)+b(6,3)+b(7,3)+b(8,3)+b(11,3) b(3,3)+b(4,3)+b(9,3)+b(10,3)+b(12,3)
我有一种方法可以做类似的事情,但只对 4 行有用。我需要修改这个脚本:
sed 's/row[1-9]//;/^$/d' file | #elimina os rows
pr -2t -w 1000|
awk 'NR==1{$1=$1; print; next}
!(NR%2){split($0,a); next}
{for(i=1;i<=NF;i++) $i+=a[i]}1' |
tr ' ' '\n' |
pr -3t
计算总和使用注意事项
$ tr -d 'ab(,)' < file > filenums
我认为有必要在 awk 部分进行修改,但我不知道该怎么做。
答案1
这是您问题的字面答案,仅使用awk
:
awk '
/column4/ { c = 3 } # add three for the second set of columns
/row/ {
row = substr($1,4) # extract the row number
col[1+c,row] = $2 # extract column 1 or 4, store in hash
col[2+c,row] = $3 # extract column 2 or 5, store in hash
col[3+c,row] = $4 # extract column 3 or 6, store in hash
}
END {
split("1 2 5 6 7 8 11", out1) # create an array of first set of rows
split("3 4 9 10 12", out2) # create an array of second set of rows
for (c = 1; c <= 6; c++) {
out = sprintf(" column%d %s", c, col[c,1]) # title and first row
for (r = 2; r <= 7; r++) {
out = out "+" col[c,out1[r]] # the rest of the first set
}
out = out " " col[c,3] # spaces, 1st row of 2nd set
for (r = 2; r <= 5; r++) {
out = out "+" col[c,out2[r]] # the rest of the 2nd set
}
print out
}
}
' file
这输出:
column1 a(1,1)+a(2,1)+a(5,1)+a(6,1)+a(7,1)+a(8,1)+a(11,1) a(3,1)+a(4,1)+a(9,1)+a(10,1)+a(12,1)
column2 a(1,2)+a(2,2)+a(5,2)+a(6,2)+a(7,2)+a(8,2)+a(11,2) a(3,2)+a(4,2)+a(9,2)+a(10,2)+a(12,2)
column3 a(1,3)+a(2,3)+a(5,3)+a(6,3)+a(7,3)+a(8,3)+a(11,3) a(3,3)+a(4,3)+a(9,3)+a(10,3)+a(12,3)
column4 b(1,1)+b(2,1)+b(5,1)+b(6,1)+b(7,1)+b(8,1)+b(11,1) b(3,1)+b(4,1)+b(9,1)+b(10,1)+b(12,1)
column5 b(1,2)+b(2,2)+b(5,2)+b(6,2)+b(7,2)+b(8,2)+b(11,2) b(3,2)+b(4,2)+b(9,2)+b(10,2)+b(12,2)
column6 b(1,3)+b(2,3)+b(5,3)+b(6,3)+b(7,3)+b(8,3)+b(11,3) b(3,3)+b(4,3)+b(9,3)+b(10,3)+b(12,3)
但是,您还提到使用tr -d 'ab(,)'
“计算总和”,我不知道您的意思;该命令只会删除您给出的字符,因此第一组 column1 的输出将变为11+21+51+61+71+81+111
.那是你要的吗?如果是这样,您是否也想将这些数字加在一起并407
在这种情况下打印?
我只是假设 a() 和 b() 是函数,你会在某个地方评估它们。如果不是,您不妨将所有内容都放在awk
.
答案2
考虑到要累积的行的选择不规则,很难设计出更通用的解决方案,最终会导致选择最优,如下所示:
sed 's/row[0-9]*//;/^$/d' file | pr -2t -w 1000 | awk '
NR==1 {split($0,h);w=NF;c=".aabbaaaabbab";next;}
substr(c,NR,1)=="a" {for(i=1;i<=NF;i++)a[i]+=$i;next;}
{for(i=1;i<=NF;i++) b[i]+=$i;}
END {for(i=1;i<=w;i++)printf"%s %d %d\n",h[i],a[i],b[i];}'
最终布局也直接从 生成awk
。显然,樱桃采摘可以通过多种不同的方式进行。这里我使用了“a”和“b”字符串来表示哪些行添加到哪个结果列中。
请注意,初始sed
表达式还需要稍作修改才能满足 9 以上的行号。