Awk 计算文本文件中列的平均值
我有两个名为f1和f2的文件夹。这些文件夹包含300个包含两列的文本文件。文件内容如下所示。我想计算第二列的平均值。两个文件夹中的文件名相同Awk 计算文本文件中列的平均值,awk,Awk,我有两个名为f1和f2的文件夹。这些文件夹包含300个包含两列的文本文件。文件内容如下所示。我想计算第二列的平均值。两个文件夹中的文件名相同 file1 in f1 folder 54 6 55 10 57 5 file2 in f1 folder 24 8 28 12 file1 in f2 folder 34 3 22 8 file2 in f2 folder 24 8 28 13 输出 folder1 folder2
file1 in f1 folder
54 6
55 10
57 5
file2 in f1 folder
24 8
28 12
file1 in f2 folder
34 3
22 8
file2 in f2 folder
24 8
28 13
输出
folder1 folder2
file1 21/3= 7 11/2=5.5
file2 20/2=10 21/2=10.5
-- -- --
-- -- --
file300 -- --
total mean of folder1 = sum of the means/3oo
total mean of folder2 = sum of the means/3oo
我会用两个
awk
脚本来完成。(最初,我在中间有一个<代码>排序/代码>阶段,但实际上这不是必要的。然而,我认为两个脚本可能比把它们组合成一个脚本更容易。如果其他人把它全部放在一起,它是可以理解的,那么选择他们的解决方案。”
运行和输出示例
这是基于问题中显示的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
这将依次处理每个文件,对第2列中的值求和并计算行数。它打印出文件夹名、文件名、总数和计数
总结2.awk
{
总和[$2,$1]=$3
cnt[$2,$1]=$4
如果(文件[$2]++==0)文件列表[n1++]=$2
如果(折叠[$1]++==0)折叠列表[n2++]=$1
}
结束{for(i=0;i
文件
关联数组跟踪对文件名的引用。file\u列表
数组按读取顺序保存文件名。类似地,折叠
关联数组跟踪文件夹名称,折叠列表
数组按文件夹名称的出现顺序跟踪文件夹名称。如果对第一个命令提供名称的顺序做了一些奇怪的事情,则可能需要在两个awk
命令之间插入sort
命令,例如sort-k2,2-k1,1
sum
关联数组包含给定文件名和文件夹名的总和。cnt
关联数组包含给定文件名和文件夹名的计数
报告的END
部分有两个主循环(尽管第一个循环包含嵌套循环)。第一个主循环按照显示的顺序处理文件,为每个文件夹生成一行,其中包含一个条目。它还累积文件夹名称的平均值。
第二个主循环为每个文件夹生成“total mean”数据。我不确定统计数据是否有意义(folder1的总体平均值不应该是folder1中的值之和除以条目数,或者41/5=8.2,而不是17/2或8.5?),但计算结果符合我认为问题的要求(平均值之和/文件数,在问题中写为300).在grep的帮助下:
grep '[0-9]' folder[12]/* | awk '
{
split($0,b,":");
f=b[1]; split(f,c,"/"); d=c[1]; f=c[2];
s[f][d]+=$2; n[f][d]++; nn[d]++;}
END{
for (f in s) {
printf("%-10s", f);
for (d in s[f]) {
a=s[f][d] / n[f][d];
printf(" %6.2f ", a);
p[d] += a;
}
printf("\n");
}
for (d in p) {
printf("total mean %-8s = %8.2f\n", d, p[d]/nn[d]);
}
}'
folder1中是否有任何文件未出现在folder2中,反之亦然?您看到在命令行上传递了哪些参数?谢谢您的详细回答。folder1和folder2中的文件数相同。。我会在几个小时内根据我的需要检查这一点,然后接受你的回答。好的,但请注意,如果你有文件
f1/n1
,f1/n2
,f2/n1
和f2/n3
,两个文件夹中的文件数量相同,但f1
中有一个文件(即n2
),而f2
中没有对应的文件,以及f2
(即n3
)中的文件,在f1
中没有对应文件。所以我问了一个比“文件数是否相同”更强的条件。但是,如果其中一个文件中存在一个与另一个文件丢失的文件,则代码将爆炸性地出现被零除的错误。这样的失败是可以证明的,但你说过这不会发生。(我的答案代码也适用于3个目录。)@leffler所有文件夹中的文件数量和名称都相同。我可以将此代码用于三个以上的目录吗?我试过像这样的awk-f summary1.awk f1/*.txt,f2/*.txt,f3/*.txt,f4/*.txt,f5/*.txt | awk-f summary2.awk。但我得到了错误。awk:无法打开f1/*.txt、f2/*.txt、f3/*.txt、f4/*.txt、f5/*.txt(没有这样的文件或目录)。我想改变你写的总平均数的公式。这是一个错误。代码不限于2或3个目录;它名义上将处理5个甚至50个目录。输出格式将非常广泛,但这是一个表象问题,而不是计算问题。命令行上的问题源于使用逗号而不是空格来分隔文件名:awk-f summary1.awk f1/*.txt f2/*.txt f3/*.txt f4/*.txt f5/*.txt | awk-f summary2.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)
}
}
grep '[0-9]' folder[12]/* | awk '
{
split($0,b,":");
f=b[1]; split(f,c,"/"); d=c[1]; f=c[2];
s[f][d]+=$2; n[f][d]++; nn[d]++;}
END{
for (f in s) {
printf("%-10s", f);
for (d in s[f]) {
a=s[f][d] / n[f][d];
printf(" %6.2f ", a);
p[d] += a;
}
printf("\n");
}
for (d in p) {
printf("total mean %-8s = %8.2f\n", d, p[d]/nn[d]);
}
}'