foo.txt
:
1 10 11
2 20 22
3 30 32
4 40 42
5 50 52
6 60 62
7 70 72
8 80 82
9 90 92
10 100 110
期望Out.txt
:
1 10 11
2 20 22
3 30 32
4 40 42
5 50 52
6 60 62
7 70 72
8 80 82
9 90 92
10 100 110
25 250 275 #Line 11
30 300 330 #Line 12
45 550 595 #Line 13
第 11 行是从第 1 行开始的第 1、第 2 和第 3 列中的交替行的总和,第 12 行是从第 2 行开始的第 1、第 2 和第 3 列中的交替行的总和。第 13 行是第 11 行和第 12 行中的列的总和。我使用的是 KSH 和 Solaris 5.10,输入文件中的值可能不是连续的,并且不会超过 3 位整数。我的输入文件只有 10 行。如何实现这一目标?
答案1
$ awk -v OFS='\t' '{for (i=1;i<=NF;i++) {s[2-NR%2,i]+=$i;s[3,i]+=$i;};$1=$1;print} END{for (n=1;n<=3;n++) print s[n,1],s[n,2],s[n,3]}' foo.txt
1 10 11
2 20 22
3 30 32
4 40 42
5 50 52
6 60 62
7 70 72
8 80 82
9 90 92
10 100 110
25 250 259
30 300 318
55 550 577
以上是在 GNU awk 和 linux 上测试的。
怎么运行的
-v OFS='\t'
可选:这将输出设置为制表符分隔。
{for (i=1;i<=NF;i++) {s[2-NR%2,i]+=$i;s[3,i]+=$i;}; $1=$1; print}
这会循环遍历每一列,将其值添加到数组中
s
。对于每一列i
,偶数行添加到s[2,i]
,奇数行添加到s[1,i]
。所有行上的列i
都添加到s[3,i]
.然后打印该行。
END{for (n=1;n<=3;n++) print s[n,1],s[n,2],s[n,3]}
到达文件末尾后,将打印结果,首先打印奇数行 (
n=1
),然后打印偶数行 (n=2
),最后打印总计 (n=3
)。
太阳/Solaris
我收到多个报告称 Sun/Solaris 上的默认 awk 有问题。请尝试:
nawk -v OFS='\t' '{for (i=1;i<=NF;i++) {s[2-NR%2,i]+=$i;s[3,i]+=$i;};$1=$1;print} END{for (n=1;n<=3;n++) print s[n,1],s[n,2],s[n,3]}' foo.txt
或者:
/usr/xpg4/bin/awk -v OFS='\t' '{for (i=1;i<=NF;i++) {s[2-NR%2,i]+=$i;s[3,i]+=$i;};$1=$1;print} END{for (n=1;n<=3;n++) print s[n,1],s[n,2],s[n,3]}' foo.txt
或者:
/usr/xpg6/bin/awk -v OFS='\t' '{for (i=1;i<=NF;i++) {s[2-NR%2,i]+=$i;s[3,i]+=$i;};$1=$1;print} END{for (n=1;n<=3;n++) print s[n,1],s[n,2],s[n,3]}' foo.txt
答案2
您几乎肯定想使用awk
这个,而不是sed
.这是一个awk
可以做到这一点的脚本:
awk '
(NR%2) == 1 {
odd_col_1 += $1;
odd_col_2 += $2;
odd_col_3 += $3;
print $0;
}
(NR%2) == 0 {
even_col_1 += $1;
even_col_2 += $2;
even_col_3 += $3;
print $0;
}
END {
print odd_col_1, odd_col_2, odd_col_3;
print even_col_1, even_col_2, even_col_3;
print odd_col_1+even_col_1, odd_col_2+even_col_2, odd_col_3 + even_col_3;
}
' foo.txt
这利用了“NR”记录号内置变量、awk
将文本文件分解为字段的方式以及“END”结构。
答案3
好吧,我自己找到了解决这个问题的一个非常基本的解决方案。但希望有人提供更好的答案。
#remove even lines
sed -i '0~2d' foo.txt > oddlines
#oddlines sum
awk '{a=a+$1}{b=b+$2}{c=c+$3}END{print a,b,c}' oddlines > oddlines_sum
#remove even lines
sed -i '1~2d' foo.txt > evenlines
#evenlines sum
awk '{a=a+$1}{b=b+$2}{c=c+$3}END{print a,b,c}' evenlines > evenlines_sum
#combine
cat evenlines_sum >> oddlines_sum
#for total sum of foo.txt
awk '{a=a+$1}{b=b+$2}{c=c+$3}END{print a,b,c}' foo.txt > foo_sum
#final output
cat oddlines_sum >> foo.txt
cat foo_sum >> foo.txt`
我知道我的解决方案非常基本。但我尽力了。
答案4
sed ' 1x;1s/^/654321/;1x;N;y/ /\n/;G;:t
s/\([0-9]*\)\n*\n\(.*\)\(.\)/l\3\1+s\3 \2/;tt
p;$!d;g;s/./l&/g;s/$/fcl3l6+l2l5+l1l4+f/' file |
dc 2>/dev/null |sed '11,$N;/\n/N;s/[^0-9] */\t/g' file -
这应该对你有用。它的工作原理是为带有流内的dc
计算器/编译器处理一些宏预处理。sed
基本上,sed
告诉dc
(bc
的编译器 - 您应该在 Solaris 系统上拥有它)跟踪 6 个值,每隔一个输入行加载一次,每列递增它们,并再次保存结果。在最后一个输入行,sed
告诉dc
再次调用它们并将所有 6 个值打印到 stdout。要获得第 13 行的总计,我们所要做的就是再次调用存储的总计并将它们相加:
l3l6+...f
我们转储dc
的 stderr ,/dev/null
因为在第一行,当它尝试l
从任何数组加载任何值时[123456]
,该数组仍为空,并且会发出警告。这没有任何意义,因为在其余时间它们不会为空,我们将在必要时保存/恢复它们。
最后,另一个sed
将整个事情粘在一起 - 它将dc
的输出附加到 的尾部file
并用每行的一个制表符替换所有空格(我\t
在这里使用了转义符,但它可能应该是实际脚本中的文字 <tab> 字符)。
输出
1 10 11
2 20 22
3 30 32
4 40 42
5 50 52
6 60 62
7 70 72
8 80 82
9 90 92
10 100 110
25 250 259
30 300 318
55 550 577