通过多个管道过滤 ping 输出失败

通过多个管道过滤 ping 输出失败

尝试仅捕获ping输出中的数据包返回时间,我发出

$ ping 192.168.0.1 | grep -o '[^ =]* ms'

它起作用了,显示每个数据包到达的时间。由于我也想摆脱时间单位,认为这就足够了:

$ ping 192.168.0.1 | grep -o '[^ =]* ms' | grep -o '^[^ ]*'

但是,令我惊讶的是,它挂起,没有显示任何输出。然而,用输出echo中的示例行替换第一个命令ping可以按预期工作(它输出5.07):

$ echo '64 bytes from 192.168.0.1: icmp_seq=10 ttl=64 time=5.07 ms' | grep -o '[^ =]* ms' | grep -o '^[^ ]*'

我找到了其他方法来仅获取没有毫秒单位的时间,但仍然:ping命令有什么问题?为什么通过一根管道可以,但通过两根管道就不行?

PS:下面的这些也失败了,而他们的echo版本成功了,因此问题不可能出在grep

$ ping 192.168.0.1 | grep -o '[^ =]* ms' | sed 's_ ms__'
$ ping 192.168.0.1 | grep -o '[^ =]* ms' | cut -f 1 -d ' '
$ ping 192.168.0.1 | cut -f 7 -d ' ' | cut -f 2 -d '='

答案1

确定的答案是行缓冲。您可以使用ping -c 3而不是仅使用 来演示这一点ping,其中所有输出仅在第一个命令完成时生成。

作为 GNU 的一种解决方法,grep您可以将两个过滤器减少为一个

ping 192.168.0.1 | grep -oP '[[:digit:].]+(?= ms)'

或者,如果您确实想使用两个过滤器,则grep --line-buffered ...stdbuf -oL grep ...都适合您。

答案2

我认为您的问题是由 shell 的行缓冲引起的。

如果您让命令运行足够长的时间,您应该会看到一些输出。
或者像这样限制 ping 数量:

$ ping -c4 192.168.0.1 | grep -o '[^ =]* ms' | grep -o '^[^ ]*'

如果您遵循此操作,则会有更多信息和解决方法(解决方案?)关联

相关内容