首页 > 解决方案 > 如何汇总仅在关键字之后的某一列的总量?

问题描述

我有下面显示的可变列的数据

...
FRAM_#     19998800      4999700(fs)  CN= 1 PRMRYTGT    13046   Ac*    14277      H  1.056      8128     CA  2.426      7589     AL  1.920
FRAM_#     19998900      4999725(fs)  CN= 1 PRMRYTGT    13046   Ac*    14277      H  1.039      8128     CA  2.311      7589     AL  1.962
FRAM_#     19999000      4999750(fs)  CN= 1 PRMRYTGT    13046   Ac*    14277      H  1.052      8128     CA  2.400      7589     AL  1.912
FRAM_#     19999100      3230225(fs)  CN= 2 PRMRYTGT    13046   Pa*    14277      H  1.064      8128     CA  2.477      7589     AL  1.930      7358     AL  2.330
FRAM_#     19999200      4523675(fs)  CN= 2 PRMRYTGT    13046   Pa*    14277      H  1.051      8128     CA  2.546      7589     AL  1.950      7358     AL  2.336
FRAM_#     19999300      4999825(fs)  CN= 1 PRMRYTGT    13046   Ac*    14277      H  0.973      8128     CA  2.385      7589     AL  2.034
FRAM_#     19999400      4999850(fs)  CN= 1 PRMRYTGT    13046   Ac*    14277      H  1.033      8128     CA  2.437      7589     AL  1.932
FRAM_#     19999500      4999875(fs)  CN= 1 PRMRYTGT    13046   Ac*    14277      H  1.015      8128     CA  2.367      7589     AL  1.979
FRAM_#     19999600      4999900(fs)  CN= 1 PRMRYTGT    13046   Ac*    14277      H  1.003      8128     CA  2.363      7589     AL  1.963
FRAM_#     19999700      4999925(fs)  CN= 1 PRMRYTGT    13046   Ac*    14277      H  1.068      8128     CA  2.467      7589     AL  1.925
FRAM_#     19999800      4999950(fs)  CN= 1 PRMRYTGT    13046   Ac*    14277      H  1.004      8128     CA  2.435      7589     AL  1.941
FRAM_#     19999900      4999975(fs)  CN= 1 PRMRYTGT    13046   Ac*    14277      H  1.062      8128     CA  2.303      7589     AL  1.911
FRAM_#     20000000      5000000(fs)  CN= 1 PRMRYTGT    13046   Ac*    14277      H  0.991      8128     CA  2.359      7589     AL  2.002
...

我想总结关键字“AL”之后的值。如果列号不同,我如何总结这些值?

我只能使用下面的代码分别计算列号为 17 或 20(在上面的示例中,我的整个数据中可能或多或少的列)

grep FRAME filename |grep "AL" | awk '{if(NF == 20){print $0}}' |awk '{s+= $20} END {print s}'

您可能会注意到第 4 行和第 5 行有两个“AL”。我想总结他们之后的价值。如果我使用上面的命令,只能总结最后一个,如果我将值 20 更改为 17,则第一个“AL”的值将丢失。更糟糕的是,我的数据超过数千,手动检查是不可行的。我希望改进我的脚本,使其对具有可变列号的数据更加机器人化?谢谢。

标签: bash

解决方案


试试这个:

grep FRAM_ filename | awk '{if ($17 == "AL") s+=$18; if(NF == 20) if ($19 == "AL") s+=$20 } END {print s}'

awk 查看每一行,如果记录 17 等于 AL,则汇总记录 18,然后检查行是否有 20 条记录,在这种情况下,如果记录 19 等于 AL,则汇总记录 20。

如果存在,最后 s 应该给你 18 和 20 位置的 AL 记录的总和。

如果不知道“AL”令牌在哪里,试试这个:

grep FRAM_ filename | awk '{ for (i=1; i<=NF; i++) if ($i == "AL") s+=$(i+1); } END {print s}'

如果文件很大,您可以避免使用 grep 并调用 awk:

awk '{ for (i=1; i<=NF; i++) if ($i == "AL") s+=$(i+1); } END {print s}' filename

推荐阅读