在管道中的相同位置收集命令

时间:2015-03-27 13:22:13

标签: bash pipe

如何在管道中的同一位置有多个命令(收集在一起)?即,管道之前的内容被分别和顺序地送入这些命令中的每一个,并且它们的组合输出被馈送到管道的下一步骤。例如,我怎么能对这个管道进行一些变化

echo -e "1\n2\n3" | { head -1; tail -1; } | xargs echo

打印1 3,而不只是1

由于

1 个答案:

答案 0 :(得分:3)

  

管道之前的内容分别按顺序送入每个命令,并将它们的组合输出送入管道的下一步

由于管道的性质,这是不可能的。从管道读取数据后,它将从管道中删除。这就是为什么只有一个读者。

我会将第一个命令的输出复制到一个临时文件中,然后将其提供给命令headtail。如果您在子shell中启动headtail,则可以将其合并输出提供给另一个命令:

顺便说一句,大括号之间的代码块不会启动子shell。你需要使用括号。以下命令似乎最接近您的要求:

echo -e "1\n2\n3" > file.tmp ; ( head -1 file.tmp ; tail -qn1 file.tmp; rm file.tmp ) | next_command

关于特殊用例:打印文件中的第一行和最后一行

我会将sed用于此目的:

sed -n '1p;$p'

这将打印文件的第一行和最后一行。但是它仅适用于包含至少两行的文件。如果文件包含一行,则会打印两次。您可以使用以下命令绕过此限制:

sed -n 'x;s/^/1/;x;1p;${x;/11/{x;p}}'

上面的命令在每一行的保持缓冲区中添加1。在脚本结束时(可能在第一行之后),它会检查保持缓冲区中是否至少有两个1,如果这是真的,则打印最后一行。