使用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’ 扩展。