使用涉及 100 多个列的长 awk 操作概括(特定)脚本

Generalize a (particular) script with a long awk operation involving 100+ columns

下面代码中手动输入的内容丰富,请只看一眼,无需看懂:

#!/bin/bash

paste A1.dat A2.dat A3.dat A4.dat A5.dat A6.dat > A.dat

awk '{print ( +  +  +  +  + ), ( +  +  +  +  + ), ( +  +  +  +  + ) + ( +  +  +  +  + 1) + ( +  +  +  +  + 3), ( +  +  +  +  + 0) + ( +  +  +  +  + 2) + ( + $ 28 +  +  +  + 4), ( +  +  +  +  + 5) + ( +  +  +  +  + 7) + ( +  +  +  +  + 9) + ( +  +  +  +  + 1) + ( +  +  +  +  + 3), ( +  +  +  +  + 6) + ( +  +  +  +  + 8) + ( +  +  +  +  + 0) + ( +  +  +  +  + 2) + ( +  +  +  +  + 4)}' A.dat >> A_full.dat

代码objective:获取存储在n 输入文件中的数据,每个文件包含 19 列数据和相等的行数。以某种方式处理此数据以生成具有 7 列数据和与每个输入文件相同的行数的输出文件。

我在上面的代码中做了什么:使用paste将所有n个输入文件(A?.dat)合并为1个文件(A.dat).接下来,我使用 awk 操作 A.dat 中的数据以获得输出文件 (A_full.dat)。对于较大的 n 值,这变得难以控制和麻烦。

我的要求:帮助我概括n的任何值的代码。我上面发布的代码适用于 n=6 的情况。要了解代码的数据操作,请查看下面 n=2 的代码(请参阅示例文件后的解释):

#!/bin/bash

paste A1.dat A2.dat > A.dat

awk '{print , ( + ), ( + ), ( + ) + ( + ) + ( + ), ( + ) + ( + ) + ( + ), ( + ) + ( + ) + ( + ) + ( +  ) + ( + ), ( + ) + ( + ) + ( + ) + ( + ) + ( + )}' A.dat >> A_full.dat

示例文件:

A1.dat:

-0.908  0.3718E-03  0.2227E-02  0.1216E-05  0.6719E-05  0.1697E-05  0.1052E-04  0.1697E-05  0.1052E-04  0.5774E-07  0.3360E-06  0.5774E-07  0.3360E-06  0.5418E-06  0.3169E-05  0.1972E-06  0.1099E-05  0.1610E-05  0.9417E-05
-0.902  0.1042E-02  0.3365E-02  0.3427E-05  0.1021E-04  0.4837E-05  0.1619E-04  0.4837E-05  0.1619E-04  0.1623E-06  0.5093E-06  0.1623E-06  0.5093E-06  0.1522E-05  0.4803E-05  0.5530E-06  0.1661E-05  0.4522E-05  0.1427E-04
-0.895  0.1962E-02  0.4677E-02  0.6479E-05  0.1428E-04  0.9232E-05  0.2289E-04  0.9232E-05  0.2289E-04  0.3064E-06  0.7100E-06  0.3064E-06  0.7100E-06  0.2870E-05  0.6694E-05  0.1042E-05  0.2310E-05  0.8530E-05  0.1988E-04
-0.889  0.3067E-02  0.6167E-02  0.1019E-04  0.1893E-04  0.1470E-04  0.3064E-04  0.1470E-04  0.3064E-04  0.4806E-06  0.9388E-06  0.4806E-06  0.9388E-06  0.4500E-05  0.8850E-05  0.1629E-05  0.3047E-05  0.1337E-04  0.2629E-04

A2.dat:

-0.908  0.9081E-04  0.5463E-03  0.9126E-05  0.5564E-04  0.4880E-06  0.3004E-05  0.4880E-06  0.3004E-05  0.2218E-06  0.1311E-05  0.2218E-06  0.1311E-05  0.1433E-06  0.8079E-06  0.1452E-06  0.8808E-06  0.4262E-06  0.2402E-05
-0.902  0.2531E-03  0.8191E-03  0.2580E-04  0.8502E-04  0.1377E-05  0.4565E-05  0.1377E-05  0.4565E-05  0.6264E-06  0.2000E-05  0.6264E-06  0.2000E-05  0.3994E-06  0.1211E-05  0.4063E-06  0.1327E-05  0.1188E-05  0.3599E-05
-0.895  0.4742E-03  0.1130E-02  0.4894E-04  0.1194E-03  0.2604E-05  0.6378E-05  0.2604E-05  0.6378E-05  0.1187E-05  0.2805E-05  0.1187E-05  0.2805E-05  0.7483E-06  0.1670E-05  0.7638E-06  0.1839E-05  0.2225E-05  0.4963E-05
-0.889  0.7357E-03  0.1480E-02  0.7735E-04  0.1591E-03  0.4094E-05  0.8448E-05  0.4094E-05  0.8448E-05  0.1874E-05  0.3729E-05  0.1874E-05  0.3729E-05  0.1161E-05  0.2186E-05  0.1191E-05  0.2419E-05  0.3452E-05  0.6496E-05

A.dat:

-0.908  0.3718E-03  0.2227E-02  0.1216E-05  0.6719E-05  0.1697E-05  0.1052E-04  0.1697E-05  0.1052E-04  0.5774E-07  0.3360E-06  0.5774E-07  0.3360E-06  0.5418E-06  0.3169E-05  0.1972E-06  0.1099E-05  0.1610E-05  0.9417E-05       -0.908  0.9081E-04  0.5463E-03  0.9126E-05  0.5564E-04  0.4880E-06  0.3004E-05  0.4880E-06  0.3004E-05  0.2218E-06  0.1311E-05  0.2218E-06  0.1311E-05  0.1433E-06  0.8079E-06  0.1452E-06  0.8808E-06  0.4262E-06  0.2402E-05
-0.902  0.1042E-02  0.3365E-02  0.3427E-05  0.1021E-04  0.4837E-05  0.1619E-04  0.4837E-05  0.1619E-04  0.1623E-06  0.5093E-06  0.1623E-06  0.5093E-06  0.1522E-05  0.4803E-05  0.5530E-06  0.1661E-05  0.4522E-05  0.1427E-04       -0.902  0.2531E-03  0.8191E-03  0.2580E-04  0.8502E-04  0.1377E-05  0.4565E-05  0.1377E-05  0.4565E-05  0.6264E-06  0.2000E-05  0.6264E-06  0.2000E-05  0.3994E-06  0.1211E-05  0.4063E-06  0.1327E-05  0.1188E-05  0.3599E-05
-0.895  0.1962E-02  0.4677E-02  0.6479E-05  0.1428E-04  0.9232E-05  0.2289E-04  0.9232E-05  0.2289E-04  0.3064E-06  0.7100E-06  0.3064E-06  0.7100E-06  0.2870E-05  0.6694E-05  0.1042E-05  0.2310E-05  0.8530E-05  0.1988E-04       -0.895  0.4742E-03  0.1130E-02  0.4894E-04  0.1194E-03  0.2604E-05  0.6378E-05  0.2604E-05  0.6378E-05  0.1187E-05  0.2805E-05  0.1187E-05  0.2805E-05  0.7483E-06  0.1670E-05  0.7638E-06  0.1839E-05  0.2225E-05  0.4963E-05
-0.889  0.3067E-02  0.6167E-02  0.1019E-04  0.1893E-04  0.1470E-04  0.3064E-04  0.1470E-04  0.3064E-04  0.4806E-06  0.9388E-06  0.4806E-06  0.9388E-06  0.4500E-05  0.8850E-05  0.1629E-05  0.3047E-05  0.1337E-04  0.2629E-04       -0.889  0.7357E-03  0.1480E-02  0.7735E-04  0.1591E-03  0.4094E-05  0.8448E-05  0.4094E-05  0.8448E-05  0.1874E-05  0.3729E-05  0.1874E-05  0.3729E-05  0.1161E-05  0.2186E-05  0.1191E-05  0.2419E-05  0.3452E-05  0.6496E-05

A_full.dat:

-0.908 0.00046261 0.0027733 1.4712e-05 8.9407e-05 3.62278e-06 2.10697e-05
-0.902 0.0012951 0.0041841 4.1655e-05 0.00013674 1.01681e-05 3.18896e-05
-0.895 0.0024362 0.005807 7.9091e-05 0.000192216 1.91659e-05 4.4386e-05
-0.889 0.0038027 0.007647 0.000125128 0.000256206 3.00122e-05 5.86236e-05

更多关于输出文件的 7 列 (A_full.dat):

起初,我以一种令人困惑的方式发布了这个问题,但在@markp-fuso 的帮助下,我对其进行了编辑,使其更容易理解。

注意:根据 OP 的最新更改(在输出中包含字段 $1)进行了更新,并结合了 EdMorton 对 awk/for 循环的建议。


基于 OP 当前的 awk 命令...

awk '{print ( +  +  +  +  + ), ( +  +  +  +  + ), ( +  +  +  +  + ) + ( +  +  +  +  + 1) + ( +  +  +  +  + 3), ( +  +  +  +  + 0) + ( +  +  +  +  + 2) + ( + $ 28 +  +  +  + 4), ( +  +  +  +  + 5) + ( +  +  +  +  + 7) + ( +  +  +  +  + 9) + ( +  +  +  +  + 1) + ( +  +  +  +  + 3), ( +  +  +  +  + 6) + ( +  +  +  +  + 8) + ( +  +  +  +  + 0) + ( +  +  +  +  + 2) + ( +  +  +  +  + 4)}' A.dat >> A_full.dat

...以及各种评论和编辑,我得出以下结论:

  • 所有输入文件都有 19 个字段
  • 所有输入文件的行数相同
  • 不确定要对字段 #1 做什么(如果有的话)(由于问题编辑和令人困惑的解释)
  • 期望的输出由每组输入行的 7x 列(col1col7)组成
  • col1:从第一个文件复制字段#1(所有输入文件中的字段#1 应该相同)
  • col2:所有输入文件中字段 #2 的总和
  • col3:(取反)来自所有输入文件的字段#3 的总和
  • col4:所有输入文件中字段#4、#6 和#8 的总和
  • col5 :(取反)来自所有输入文件的字段#5、#7 和#9 的总和
  • col6:所有输入文件中字段#10、#12、#14、#16 和#18 的总和
  • col7:所有输入文件中字段#11、#13、#15、#17 和#19 的总和
  • 现在我假设我们希望输出行按照从输入文件中读取的相同顺序排序(即输入 NR == 输出 NR)
  • OP 需要一个可以处理 n 个输入文件
  • 的解决方案

而不是 paste(ing) n 输入文件到一个大文件 (A.dat) 然后让 awk 解析 n x 19列,我建议 awk 读取单个数据文件 (A?.dat) 并累积所需的数据值 'on the fly'.

一个awk解法:

awk '
FNR==NR { col1[FNR]= }
        { col2[FNR]+=()
          col3[FNR]-=()
          col4[FNR]+=( +  + )
          col5[FNR]-=( +  + )
          col6[FNR]+=( +  +  +  + )
          col7[FNR]+=( +  +  +  + )
        }
END     { for ( i=1 ; i <= FNR ; i++ )
              printf "%s %7.5f %7.5f %8.6f %8.6f %d %d\n", col1[i], col2[i], col3[i], col4[i], col5[i], col6[i], col7[i]
    }
' A1.dat A2.dat A3.dat ... An.dat

注意printf格式基于OP提供的有限样本输出;可能需要根据来自更大数据集的所需结果来调整这些。

注意:这个awk解决方案的一个缺点是我们必须将所有(输出)数据存储在一组数组中,这反过来可能导致如果我们处理大量的行,内存使用问题。

将 OPs 示例输入文件 (A.dat) 解析回前 2 个原始数据文件:

$ cat A1.dat
  4.429  0.3620E-01  0.3919E-01  0.1063E-01  0.9525E-02  0.9146E-02  0.7986E-02  0.9146E-02  0.7986E-02  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00
  4.436  0.3489E-01  0.3876E-01  0.1022E-01  0.9461E-02  0.8803E-02  0.7872E-02  0.8803E-02  0.7872E-02  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00
  4.442  0.3364E-01  0.3852E-01  0.9760E-02  0.9469E-02  0.8402E-02  0.7801E-02  0.8402E-02  0.7801E-02  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00
  4.449  0.3260E-01  0.3917E-01  0.9364E-02  0.9753E-02  0.8040E-02  0.8083E-02  0.8040E-02  0.8083E-02  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00

$ cat A2.dat
   4.429  0.4333E-01  0.3393E-01  0.6788E-02  0.6654E-02  0.8228E-02  0.7242E-02  0.8228E-02  0.7242E-02  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00
   4.436  0.4101E-01  0.3372E-01  0.6687E-02  0.6563E-02  0.7849E-02  0.7179E-02  0.7849E-02  0.7179E-02  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00
   4.442  0.3861E-01  0.3437E-01  0.6561E-02  0.6437E-02  0.7440E-02  0.7192E-02  0.7440E-02  0.7192E-02  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00
   4.449  0.3646E-01  0.3667E-01  0.6462E-02  0.6514E-02  0.7091E-02  0.7443E-02  0.7091E-02  0.7443E-02  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00  0.0000E+00

运行 建议的 awk 针对这些 2x 输入文件的解决方案生成:

$ awk '{ col1[FNR]+= .... }' A1.dat A2.dat
4.429 0.07953 -0.07312 0.052166 -0.046635 0 0
4.436 0.07590 -0.07248 0.050211 -0.046126 0 0
4.442 0.07225 -0.07289 0.048005 -0.045892 0 0
4.449 0.06906 -0.07584 0.046088 -0.047319 0 0