使用管道有什么区别吗?

使用管道有什么区别吗?

使用Ubuntu 12.04。

使用管道(5次):

$ time echo XYZ | sed 's/X/A/g' | sed 's/Y/B/g' | sed 's/Z/C/g'
ABC

real    0m0.005s
user    0m0.000s
sys 0m0.000s
$ time echo XYZ | sed 's/X/A/g' | sed 's/Y/B/g' | sed 's/Z/C/g'
ABC

real    0m0.004s
user    0m0.000s
sys 0m0.000s
$ time echo XYZ | sed 's/X/A/g' | sed 's/Y/B/g' | sed 's/Z/C/g'
ABC

real    0m0.004s
user    0m0.004s
sys 0m0.000s
$ time echo XYZ | sed 's/X/A/g' | sed 's/Y/B/g' | sed 's/Z/C/g'
ABC

real    0m0.005s
user    0m0.000s
sys 0m0.000s
$ time echo XYZ | sed 's/X/A/g' | sed 's/Y/B/g' | sed 's/Z/C/g'
ABC

real    0m0.005s
user    0m0.004s
sys 0m0.000s

不使用管道(5次):

$ time echo XYZ | sed 's/X/A/g; s/Y/B/g; s/Z/C/g'
ABC

real    0m0.003s
user    0m0.000s
sys 0m0.004s
$ time echo XYZ | sed 's/X/A/g; s/Y/B/g; s/Z/C/g'
ABC

real    0m0.003s
user    0m0.000s
sys 0m0.000s
$ time echo XYZ | sed 's/X/A/g; s/Y/B/g; s/Z/C/g'
ABC

real    0m0.003s
user    0m0.000s
sys 0m0.000s
$ time echo XYZ | sed 's/X/A/g; s/Y/B/g; s/Z/C/g'
ABC

real    0m0.003s
user    0m0.004s
sys 0m0.000s
$ time echo XYZ | sed 's/X/A/g; s/Y/B/g; s/Z/C/g'
ABC

real    0m0.003s
user    0m0.000s
sys 0m0.000s
$ 

很明显,不使用管道会更快。所以它可以用来优化脚本:

$ echo ABC | sed 's/A/X/g; s/X/Y/g'
YBC
$ 

我的问题:合并 sed 总是产生相同的输出?

答案1

简短的回答是,当你使用管道要执行不同的替换,shell 需要多次分叉。

另一方面,sed包含各种替换命令的表达式要求 shell 仅分叉一次。

因此,在单个表达式中包含各种命令会更有效,例如:

sed 's/X/A/g; s/Y/B/g; s/Z/C/g'

回答第二部分,上面相当于下面慢点变体:

sed 's/X/A/g' | sed 's/Y/B/g' | sed 's/Z/C/g'

答案2

是的,您发布的两个命令 100% 等效,因此您可以安全地更改脚本以不使用管道。

但你的推理是有缺陷的:你只测量了 所需的时间echo XYZ,而不是实际的sed调用。然而,您会发现不使用管道仍然更快:)

dennis@spirit:~$ time sh -c 'echo XYZ | sed -e s/X/A/ | sed -e s/Y/B/ | sed -e s/Z/C/'
ABC

real    0m0.009s
user    0m0.000s
sys 0m0.012s
dennis@spirit:~$ time sh -c 'echo XYZ | sed -e s/X/A/ -e s/Y/B/ -e s/Z/C/'
ABC

real    0m0.006s
user    0m0.000s
sys 0m0.006s

答案3

还有一个 GNU 扩展可以sed为您有条件地分叉:

sed '/num/s//echo "$((num+1))"/e'

info sed

e

该命令允许将 shell 命令的输入通过管道传送到模式空间。如果进行了替换,则执行在模式空间中找到的命令,并用其输出替换模式空间。尾随换行符被抑制;如果要执行的命令包含 NUL 字符,则结果未定义。

这是一个 GNU ‘sed’ 扩展。

相关内容