【问题标题】:AWK / Linux script calculations from a text file来自文本文件的 AWK / Linux 脚本计算
【发布时间】:2016-10-21 15:36:38
【问题描述】:

我编写了一个 AWK 脚本,它读取文件并将行与列相乘并将它们相加。我想一次将多个文件(任意数量的文件)作为参数传递给 awk 脚本,例如A.txt、B.txt、C.txt。我希望 AWK 脚本给我行和列的总和。我总是想跳过每个文本文件的前 5 列。

每个文本文件可以有任意数量的列。一个文件夹内可以有多个文本文件。

我想运行:

awk -f foo.awk A.txt B.txt C.txt

例如

如果有 3 个不同的文件 A.txt、B.txt、C.txt,将每 3 个文件的行和列相乘相加。

输出应该是:

No of columns in A.txt: count of columns in A.txt with first 5 columns ignored
No of columns in B.txt: count of columns in B.txt with first 5 columns ignored
No of columns in C.txt: count of columns in C.txt with first 5 columns ignored
Sum of A.txt: rows in A.txt*columns in A.txt
Sum of B.txt: rows in B.txt*columns in B.txt
Sum of C.txt: rows in C.txt*columns in C.txt
Total Sum: A+B+C

以下是(某种伪代码)到目前为止我对 foo.awk 的了解(它不适用于多个文件):

#!/bin/gawk -f

BEGIN { rows=0; columns=0 }
{
    FS="\t";
    if(/^#COLS/) {
            column=NF-5; #skip first 5 columns
            columns+=column
    }
    if (!/^#/){
            rows++;
            files[FILENAME]++;
    }
}
END {
    for (fname in files) {
            printf ("%'24d rows in %s\n",files[fname],fname);
    }
            printf("No of columns in A.txt= %'d\n", columnsA);
            printf("No of columns in B.txt= %'d\n", columnsB);
            printf("No of columns in C.txt= %'d\n", columnsC);
            sum=columns*rows; # multiply no of rows by column in each file and add them up 
            printf( "Sum of A.txt %d\n", sumA);
            printf( "Sum of B.txt %d\n", sumB);
            printf( "Sum of C.txt %d\n", sumC);   
            printf( "Total sum is %d\n", sum_of_A+B+C);  
}

例如

A.txt:
#ignore this line -- pattern does not match
#ignore this line -- pattern does not match
#COLS   A       B       C       D       E       F       G       H       I 
row1    1       2       3       4       5       6       7       8       9
row2    1       3       3       4       5       6       7       8       9
row3    1       3       3       4       5       6       7       8       9

B.txt:
#ignore this line -- pattern does not match
#ignore this line -- pattern does not match
#COLS   A       B       C       D       E       F       G       H        
row1    1       2       3       4       5       6       7       8       
row2    5       3       3       4       6       6       7       8       
row3    8       3       3       4       5       6       7       8       

C.txt:
#ignore this line -- pattern does not match
#ignore this line -- pattern does not match
#COLS   A       B       C       D       E       F       G       H       I       J
row1    1       2       3       3       5       6       7       8       9       2
row2    7       3       3       4       5       6       7       8       9       7
row3    9       3       3       4       5       6       7       8       9       6
row4    9       3       3       4       5       6       7       8       9       6

output:

No of columns in A.txt: 5
No of columns in B.txt: 4
No of columns in C.txt: 6
Sum of A.txt: 3*5=15
Sum of B.txt: 3*4=12
Sum of C.txt: 4*6=24
Total Sum: 12+9+20 = 51

谢谢。

【问题讨论】:

  • 对 awk 不是很熟悉,但我认为您需要使用文件构造 BEGINFILE 和 ENDFILE,这可能是 gawk 特定的...
  • @Sundeep 这是 gawk 特定的,请参阅 manual - 但如果 gawk 可用,IMO 是最好的解决方案。
  • @BenjaminW。感谢您的澄清.. 刚刚注意到 OP 使用了#!/bin/gawk -f
  • 请提供几个示例文件和预期的输出。这太令人困惑了。
  • 已更新示例,谢谢

标签: linux bash shell unix awk


【解决方案1】:

使用普通的awk 你可以做到这一点

$ awk '!/^#/{cols[FILENAME]=NF-5; 
             rows[FILENAME]++} 
         END{for(f in cols) print "No of columns in " f, cols[f]; 
             for(f in cols) 
               {r=rows[f];
                c=cols[f];
                sum+=r*c; 
                sumstr=sumstr?sumstr"+"r*c:r*c; 
                print "Sum of "f ":",r "x" c "=" r*c} 
             print "Total Sum: ", sumstr, "=", sum}' {A,B,C}.txt

No of columns in C.txt 6
No of columns in B.txt 4
No of columns in A.txt 5
Sum of C.txt: 4x6=24
Sum of B.txt: 3x4=12
Sum of A.txt: 3x5=15
Total Sum:  24+12+15 = 51

列数不匹配,您是跳过 5 还是 6。另请注意,条目的顺序不会保留,可以使用 gawk sorted-in 来修复,或者像下面这样几乎没有额外的编码.. .

$ awk 'FNR==1{order[++k]=FILENAME} 
        !/^#/{cols[FILENAME]=NF-5; rows[FILENAME]++} 
          END{for(i=1;i<=k;i++) print "No of columns in " order[i], cols[order[i]]; 
              for(i=1;i<=k;i++) {f=order[i];r=rows[f];c=cols[f];sum+=r*c; sumstr=sumstr?sumstr"+"r*c:r*c; print "Sum of "f ":",r "x" c "=" r*c} 
              print "Total Sum: ", sumstr, "=", sum}' {A,B,C}.txt

No of columns in A.txt 5
No of columns in B.txt 4
No of columns in C.txt 6
Sum of A.txt: 3x5=15
Sum of B.txt: 3x4=12
Sum of C.txt: 4x6=24
Total Sum:  15+12+24 = 51

【讨论】:

  • 谢谢。但是您的脚本不查找#COLS 或# 模式。可以更新一下吗?
  • 所有行的列数是否相同是否重要?如果没有,行 * 列无论如何都不会给你元素的数量。
  • 哦,你也在跳行!
  • 我正在尝试获取每个文件 A.txt、B.txt 等中的总列数。我想将每个文件中的行数乘以每个文件中的列数。最后,我想对每个文件的行和列求和。
  • 对于我使用的输入和生成的输出,您认为哪些信息缺失或不正确?如果是这样,请在您的原始帖子中创建一个最小输入集和预期输出,这样其他人也不会感到困惑。
猜你喜欢
  • 2011-09-20
  • 2012-08-09
  • 2015-04-24
  • 1970-01-01
  • 2014-11-26
  • 2018-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多