【问题标题】:awk: how to execute a command and read its outputawk:如何执行命令并读取其输出
【发布时间】:2013-02-05 13:04:47
【问题描述】:

我想从标准输入读取数据并为每个解析的行执行一个 shell 命令并恢复其输出。

这是一个几乎可以工作的例子:

[root@eulbi002] # ping eulbi001 | awk -F'[ =]' '/64 bytes/{"date +%s"|getline D; print D,$11}'
1360069298 0.056
1360069298 0.051
1360069298 0.051

命令 'date +%s' 已执行,我可以恢复输出,但在我看来,执行只发生一次,而不是每次匹配。

最终目的是将输出交给 rrdtool 进行存储,而 rrdtool 想要每条记录的时间戳。

@Ed Morton 除了指出一个可行的解决方案外,还提到了 gawk 及其内置的时间功能。这是最优雅的解决方案。

[root@eulbi002] # ping eulbi001 | awk -F'[ =]' '/64 bytes/{print systime(),$11}'
1360069298 0.056
1360069298 0.051
1360069298 0.051

【问题讨论】:

  • date 每行都被调用,但所有输出都在 1 秒内被解析。
  • 抱歉,不明白您的评论。如果对每一行都执行日期,那么我应该会看到变量 D 也增加了。
  • 如果每次调用 date 都与上次调用 date 时间在同一秒内,则不会。您告诉 date 打印自纪元以来的秒数,因此 D 只会每秒更改一次,而不是每次调用 date 时都更改..
  • ping 每秒都会给我一个新行,所以日期也应该每秒运行一次,这在我上面的测试中不是这种情况。这就是我在这里提出这个的唯一原因。

标签: awk


【解决方案1】:

以防万一此处出现另一个 getline 警告(请参阅 http://awk.info/?tip/getline),请尝试在每次调用后关闭管道,例如:

ping eulbi001 |
awk -F'[ =]' 'BEGIN{cmd="date +%s"} /64 bytes/{cmd|getline D; close(cmd); print D,$11}'

看看你是否得到不同的结果。但是,您仍然不应该期望 D 在每次调用时都会更改,只是每秒更改一次。如果您愿意,您可以添加“.%N”以获得更小粒度的时间戳。

更好的是,使用带有内置时间函数的 GNU awk,因此您根本不需要处理这些东西。

【讨论】:

    最近更新 更多