0

我有两个名为 f1 和 f2 的文件夹。这些文件夹包含 2 列的 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         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
4

2 回答 2

2

我会用两个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)。

于 2013-06-03T20:10:08.043 回答
0

在 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]);
      }
    }'
于 2013-06-03T22:11:24.937 回答