我偶然发现了一个小问题,我无法在 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 作为返回值。也许我只遗漏了一件小事,但不幸的是我在网上找不到任何东西。解决此问题的最佳方法是什么。
感谢您的帮助。
干杯。
最佳答案
尝试:
awk 'NR==1 {time=$4;next} {sum+=$3} END {print time, (sum/(NR-1))}' $tmpn.data >>$tmpn.vrms
NR==1 {time=$4;next}
是模式 Action 对:- 模式(条件)
NR==1
仅适用于第一行输入。 - 因此,操作
{time=$4;next}
仅在第一行执行,并将 header 的第 4 个字段存储在变量time
中,然后继续下一条记录(行;next
)。
- 模式(条件)
{sum+=$3}
,它针对所有剩余记录(即 data 记录)进行处理,迭代地对变量sum
中的第三个字段中的值求和。 .END {print time, (sum/(NR-1))}
:END
处理完所有输入记录后执行 block 。-
{print time, (sum/(NR-1))}
打印标题字段和第 3 个字段值的平均值,由默认输出字段分隔符 (OFS
) 分隔,这是一个空格。注意NR
包含END
中的输入记录总数阻止。
关于您的解决方案尝试的注释和 awk
的理念:
如(当前)所述,您的命令中断,因为您已将整个脚本包含在
{...}
中.一般来说,
awk
的简洁优雅来自一系列精心制作的模式 Action 对。- 模式 是一个条件( bool 表达式),只有在条件为真时才执行相关的操作(一系列语句)。
- 将模式视为
if
的条件部分删除了“句法噪声”的语句,并将 Action 作为该语句的主体if
声明:
<pattern> { <action-cmd1>; ... }
是(概念上)if (<pattern>) { <action-cmd1>; ... }
的缩写
在给定的对中,您可以省略 Action 或模式:
如果您省略模式,操作将无条件执行(尽管该操作可能如果之前的模式- Action 对跳过了进一步的处理,例如
next
或exit
,仍然无法执行。如果您省略操作,默认操作是
{ print }
,即打印(可能修改过的)当前记录。- 此行为启用常用速记
1
简单地打印当前记录:1
是一种模式,在评估模式的 bool 上下文中,它始终为真,并且在没有关联操作的情况下,默认打印当前记录。
- 此行为启用常用速记
关于bash - 用awk在列中打印某些参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40227455/