我会用两个awk
脚本来做。(最初,我sort
在中间有一个阶段,但这实际上不是必需的。但是,我认为两个脚本可能比尝试将它们组合成一个更容易。如果其他人“全部合二为一”,那就是可以理解,然后选择他们的解决方案。)
样品运行和输出
这是基于问题中显示的 4 个文件。文件名列在命令行上,但顺序无关紧要。代码假定文件名中只有一个斜杠,文件名中没有空格等。
$ awk -f summary1.awk f?/* | awk -f summary2.awk
file1 21/3 = 7.000 11/2 = 5.500
file2 20/2 = 10.000 21/2 = 10.500
total mean of f1 = 17/2 = 8.500
total mean of f2 = 16/2 = 8.000
摘要1.awk
function print_data(file, sum, count) {
sub("/", " ", file);
print file, sum, count;
}
oldfile != FILENAME { if (count > 0) { print_data(oldfile, sum, count); }
count = 0; sum = 0; oldfile = FILENAME
}
{ count++; sum += $2 }
END { print_data(oldfile, sum, count) }
这将依次处理每个文件,将第 2 列中的值相加并计算行数。它打印出文件夹名称、文件名、总和和计数。
摘要2.awk
{
sum[$2,$1] = $3
cnt[$2,$1] = $4
if (file[$2]++ == 0) file_list[n1++] = $2
if (fold[$1]++ == 0) fold_list[n2++] = $1
}
END { for (i = 0; i < n1; i++)
{
printf("%-20s", file_list[i])
name = file_list[i]
for (j = 0; j < n2; j++)
{
folder = fold_list[j]
s = sum[name,folder]
n = cnt[name,folder]
a = (s + 0.0) / n
printf(" %6d/%-3d = %10.3f", s, n, a)
gsum[folder] += a
}
printf("\n")
}
for (i = 0; i < n2; i++)
{
folder = fold_list[i]
s = gsum[folder]
n = n1;
a = (s + 0.0) / n
printf("total mean of %-6s = %6d/%-3d = %10.3f\n", folder, s, n, a)
}
}
file
关联数组跟踪对文件名的引用。该file_list
数组按读取顺序保存文件名。类似地,fold
关联数组跟踪文件夹名称,fold_list
数组按照文件夹名称出现的顺序跟踪它们。如果您按照为第一个命令提供名称的顺序做了一些奇怪的事情,您可能需要sort
在两个命令之间插入一个awk
命令,例如sort -k2,2 -k1,1
.
sum
关联数组包含给定文件名和文件夹名的总和。cnt
关联数组包含给定文件名和文件夹名的计数。
报告END
部分有两个主要循环(尽管第一个循环包含一个嵌套循环)。第一个主循环按呈现的顺序处理文件,为每个文件夹生成包含一个条目的一行。它还累积文件夹名称的平均值。第二个主循环为每个文件夹生成“总平均值”数据。我不确定统计数据是否有意义(folder1 的总体平均值不应该是 folder1 中的值的总和除以条目数,还是 41/5 = 8.2 而不是 17/2 或 8.5?),但计算完成了我认为问题所要求的(均值之和/文件数,在问题中写为 300)。