使用awk在列中打印某些参数

时间:2016-10-24 20:59:19

标签: bash awk

我偶然发现了一个小问题,我无法用bash脚本中的awk解决这个问题。

我确实有以下数据文件:

 33   1000   1.108932e-01   2.825803e+00  -9.955642e-05    0.0000e+00       0.0000e+00    8.012180e-02 4.081916e-02

 0.0000e+00   7.8557e-01   6.1128e+01   4.0468e+00  -9.9558e-05   3.8526e-02   3.1874e-03   5.1303e-01   0.0000e+00

 1.6667e-02   7.8530e-01   6.0977e+01   4.0552e+00   1.0627e-01   7.8951e-02   6.2521e-03   5.0750e-01   0.0000e+00

...

其标题行包含10个元素,后跟一个包含33行和9列的数组。

我想使用此文件中的数据从标题行打印出第四个参数,然后是第3行的平均值(即sum+=$3 / {Number of lines})。目前,我尝试这样做:

gawk '{time=FNR==1{$4};if(NR>1)sum+=$3}; time = FNR == 1{$4} END {sum=sum/(NR-1); print time " " sum}' $tmpn.data >> $tmpn.vrms

它适用于平均值,但是,时间参数不正确,我只得到0作为返回。也许我只缺少一件小事,但不幸的是我无法在网上找到任何东西。什么是解决这个问题的最佳方法。

感谢您的帮助。

干杯。

2 个答案:

答案 0 :(得分:3)

尝试:

awk 'NR==1 {time=$4;next} {sum+=$3} END {print time, (sum/(NR-1))}' $tmpn.data >>$tmpn.vrms
  • NR==1 {time=$4;next}是一个模式 - 动作对:

    • 模式(条件)NR==1仅适用于第一个输入行。
    • 因此,仅对第一行执行操作{time=$4;next},并将标题的第4个字段存储在变量time中,然后进入下一条记录(行; {{1 }})。
  • next,为所有剩余记录(即数据记录)处理,迭代地汇总变量{sum+=$3}中第3个字段中的值

  • sum

    • 在处理完所有输入记录后执行END {print time, (sum/(NR-1))}块。
    • END打印标题字段和第3个字段值的平均值,由默认输出字段分隔符({print time, (sum/(NR-1))})分隔,这是一个空格。请注意,OFS包含NR块内的输入记录总数。

关于您的解决方案尝试的说明和END的哲学

  • 正如(目前)所述,您的命令会中断,因为您已将整个脚本包含在awk中。

  • 通常, {...}简洁优雅来自精心设计的模式动作的 序列

    • 模式是一个条件(布尔表达式),只有在条件为真时才执行关联的操作(一系列语句)。
    • 将模式视为awk语句的条件部分,使用"语法噪音"删除,并将该操作作为if语句的主体:
      if }(概念上)是<pattern> { <action-cmd1>; ... }
    • 的缩写
  • 在给定的一对中,您可以省略操作或模式

    • 如果您省略模式 ,则操作无条件执行 (尽管此操作可能如果之前的模式操作对跳过进一步处理(例如使用if (<pattern>) { <action-cmd1>; ... }next),则仍然无法执行。

    • 如果忽略操作 ,则默认操作为exit ,即打印(可能)当前记录。

      • 此行为使公共简写{ print }能够简单地打印当前记录:1是一种模式,在评估模式的布尔上下文中,它始终为true,并且在如果没有相关的操作,默认情况下会打印当前记录。

答案 1 :(得分:0)

awk中的另一个版本在getline循环中使用while来读取和检测文件结尾,然后输出标头缓冲区b和平均值:

$ awk 'NR==1{b=$4; while(getline==1){s+=$3;c++} print b,s/c}' data
4th 40.7386

它希望data文件有一个标题行。说明:

NR==1 {                  # read in the first line and ...
    b=$4                 # ... buffer the 4th field of the header 
    while(getline==1) {  # then read while there are records to read
        s+=$3            # sum up the values in the 3rd field
        c++              # count the number of values, add if($3!="") if needed
    } 
    print b, s/c         # after while output header and average
}
相关问题