无法捕获paste bash命令的输出

时间:2015-05-09 20:18:30

标签: bash shell scripting

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

由于某些原因似乎没有工作,而如果我带走了

| paste - -

部分,它运作得很好。我需要使用制表符而不是换行符连接所有其他行。任何想法都表示赞赏。

2 个答案:

答案 0 :(得分:2)

<强>更新

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

因此,您需要限制执行的ping数量; e.g:

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

顺便提一下,为了将管道重定向到文件, no 需要将它整合在(...)中,这会不必要地创建一个(另一个)子shell < / em>的

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

tivn's answer在您的命令中至少发现了潜在的问题:假设time总是有一个小数点,而不是坚持 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=([^ ]+).*$/\1'$'\t''\2/'

替代解决方案,使用awk

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

如果你不想依赖字段索引,这里有一个替代方案(仍然依赖字段icmp_seq time之前的,并且两者都以空格开头):

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

答案 1 :(得分:1)

您没有提供从ping获得的示例输入,因此不清楚您的问题是什么。但我想您的问题是因为time结果中的ping部分可能并不总是包含点.,例如: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命令。