无法捕获过去 bash 命令的输出

Can't capture the ouput of the paste bash command

( ping -n apple.com | ack -o --flush '((?<=icmp_seq=)[0-9]+|(?<=time=)[0-9]+[.][0-9]+)' | paste - - ) > ~/Desktop/ping_ouput.txt

由于某种原因似乎无法正常工作,而如果我拿走

| paste - -

节,效果很好。我需要用制表符而不是换行符将每一行连接在一起。任何想法表示赞赏。

更新:

默认情况下,ping 无限期地产生输出 ,直到终止 ,因此您的管道将继续产生输出并增加无限期地输出文件,你的命令永远不会自己完成

因此,您需要限制执行的 ping 次数;例如:

  • 使用 -c count 选项在指定的 ping 次数后停止。
  • 或者,在类似 BSD 的系统上,您可以使用 -o 在第一个 成功 ping 之后停止。
  • 或者,您可以在指定的超时秒数后停止,而不管收到了多少数据包:
    • Linux: -w timeout
    • 类 BSD 系统:-t timeout

顺便说一句,为了将管道重定向到文件,不需要将它作为一个整体包含在(...)中,这不必要地创建了一个(另一个) 子壳.


以下内容是在 (a) 已知特定症状和 (b) OP 在评论中透露他们的平台是 OSX 之前编写的。下面的命令显示了 OP 提取命令的替代方法; -c 2 已添加以将 ping 限制为 2 次尝试。

在您的命令中发现了至少 潜在的 问题:假设 timealways有一个小数点,在 Linux 平台上不成立;然而,在 BSD/OSX 平台上,总是 3 位小数。

您可以绕过这个问题以及合并连续行的需要,如下所示(我使用 127.0.0.1 而不是 apple.com 以便于测试):

使用 GNU sed (Linux) 或 BSD sed(类 BSD 系统,包括 OSX):

ping -c 2 -n 127.0.0.1 |
  sed -E '1d; s/^.* icmp_seq=([^ ]+).* time=([^ ]+).*$/'$'\t''/'

备选方案,使用awk

ping -c 2 -n 127.0.0.1 | awk -F'[ =]' -v OFS='\t' 'NR>1 { print ,  }'

如果您不想依赖字段 indices,这里有一个替代方案(仍然依赖字段 icmp_seqbefore time,并且两者前面都有 space):

ping -c 2 -n 127.0.0.1 | awk -F' (icmp_seq|time)=' -v OFS='\t' '
  NR>1 { sub(" .+$", "", ); sub(" .+$", "", )
  print ,  }'

您没有提供从 ping 获得的样本输入,因此不清楚您的问题是什么。但我猜你的问题是因为 ping 结果中的 time 部分可能并不总是包含点 .,例如: 64 bytes from x.x.x.x: icmp_seq=1 ttl=63 time=137 ms 。您可能想尝试使用以下命令:

( ping -n yahoo.com \
  | ack -o --flush '((?<=icmp_seq=)\d+|(?<=time=)[\d.]+)' \
  | stdbuf -o0 paste - - \
) > ~/Desktop/ping_ouput.txt

编辑:根据 OP 的评论,问题实际上可能来自缓冲的 paste 命令。请尝试将 stdbuf -o0 添加到 paste 命令。