Zsh输出重定向行为

3
在中:
bash% echo xxx >&2 | wc
xxx
   0   0   0

在zsh中:
zsh% echo xxx >&2 | wc
xxx
   1   1   4
zsh% { echo xxx >&2; } | wc
xxx
   0   0   0

我如何让zsh在此情况下表现得像bash? 是否有设置zsh的选项?

2个回答

4

如果要更改即兴的行为,您可以简单地使用括号

(echo xxx >&2) | wc

请注意,这里添加括号没有副作用,因为即使没有括号,由于使用了管道(|),您的命令也会在子shell中运行。
要更改整个shell的行为,请参见@chepner's answer

性能考虑:

@chepner在评论中问是否括号会导致一个额外的子shell(从而导致子进程)。

令人惊讶的答案是相反的:
使用选项MULTIOS ON(默认情况下),使用括号会导致少1个子shell。

如果选项MULTIOS关闭,则括号(此时不需要)没有任何区别。


我是如何测试的:

在 OS X 10.9.2 上,我使用 sudo dtruss -t fork -f -p {pidOfZsh} 来监控一个 zsh shell 中的 fork() 调用;zsh 的版本为 zsh 5.0.2 (x86_64-apple-darwin13.0)

在打开选项 MULTIOS 的情况下,echo xxx >&2 | wc 共分叉了 3 次,而 (echo xxx >&2) | wc 只分叉了 2 次。


zsh 是否对此进行优化,还是仅在由管道创建的子shell中启动另一个子shell? - chepner

3
关闭MULTIOS选项可以改变这种行为。
% echo xxx >&2 | wc
xxx
       1       1       4
% setopt NOMULTIOS
% echo xxx >&2 | wc
xxx
       0       0       0

使用该选项后,单个命令可以进行多个IO重定向,为此目的,管道符被视为其中一个。


根据http://zsh.sourceforge.net/Doc/Release/Redirection.html#Multios,启用`MULTIOS`后,`echo xxx >&2 | wc似乎会将stdout同时输出到stderr(2)wc`。 - aggu
在我发布这篇文章之后,我在man zshmiscMULTIOS部分找到了一条注释,指出管道被视为标准输出的隐式重定向。 - chepner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接