我需要帮助来通过 awk 处理列条目。以下是我想尝试的操作:
- 以用户定义的块大小划分列;
- 计算并总结每个块的每个条目,最终得出每个条目的平均值,即最终的块大小。
例如,下面是一个列表:
1
2
3
4
5
6
7
8
9
10
11
12
在这里,我想使用 4 的块大小(但在我的情况下,它可能因情况而异):
- 块1
1 2 3 4
- 块2
5 6 7 8
- 块3
9 10 11 12
处理后,我想要:
5
6
7
8
这是所有块中位置 1、2、3 和 4 的条目的平均值。
答案1
下面的awk
程序可以完成这项工作。它假设数据存储data.txt
在第一列中(但可以轻松地适应任何其他列)。它还假设没有空列,只有完整的块。
awk -v cs=4 '{if ((i=NR%cs)==0) {n_ch++; i=cs};buf[i]+=$1;} END{for (i=1;i<=cs;i++) printf "%d\n",buf[i]/n_ch}' data.txt
awk
块大小通过语句传递。-v cs=size
对于每一行,它将确定“块内的条目号”,i
通过
i = "line number" modulo "chunk size"
,并将条目求和到一个数组中buf
。每当一个块完成时,块计数器n_ch
就会增加。
最后,我们打印所有条目数的平均值。
答案2
awk -v cs=4 '
BEGIN {
"(wc -l <" ARGV[1] ")" | getline nl
nc = sprintf("%d", nl/cs)
}
{ a[NR%cs] += $1 }
NR>nl-cs { print a[NR%cs]/nc }
' file
5
6
7
8
- 在 begin 块中,我们确定文件中的行并将其存储在 nl 变量中。
- 然后我们得到块的数量并将其存储在 nc 变量中。
- 将运行总和累加到以行号 % 块大小为模数索引的数组中。
- 然后,当行号超过 nl-cs 的阈值时,意味着我们正在进入最后一个块,我们开始打印结果。
或者,如果我们不想预先计算文件长度和块数,我们可以这样做:
awk -v cs=4 '
{ a[NR] = $1 }
END {
for (i=1; i<=cs; i++) {
k = s = 0
for (j=i; j<=NR; j+=cs) {
s += a[j]; k++
}
print s/k
}
}
' file
答案3
另一种方法awk
是在运行过程中对每个块中的元素进行计数,因此如果记录计数不是精确的块倍数,这并不重要,它仍然是平均值
awk -v ch=4 '{k=(NR-1)%ch; n[k]++; un[k]+=$1}
END{for (k in un) print "Line "k+1" has "n[k]" elements totalling "un[k]" and average "un[k]/n[k]}' file
Line 1 has 3 elements totalling 15 and average 5
Line 2 has 3 elements totalling 18 and average 6
Line 3 has 3 elements totalling 21 and average 7
Line 4 has 3 elements totalling 24 and average 8
虽然END
不必是描述性的
END{for (k in un) print un[k]/n[k]}' file
5
6
7
8
如果你想保证输出顺序
END{for (k=0; k<ch; k++) print un[k]/n[k]}' file