Answers:
是的,可以在bash中使用括号:
(A && B || C) | D
这样的输出A && B || C
将通过管道传递到D
。
sh
:)中使用括号
A
位于子外壳中,因此也包括A
。)
你可以这样写
if A; then B; else C; fi | D
您说您想运行B
或C
,但是A && B || C
没有实现。如果A
成功,但是B
运行失败,它将执行C
。
注意1:如果您能以某种方式保证B
总是成功并且想坚持使用简短版本,那么我仍然会选择
{ A && B || C; } | D
结束( ... )
,因为后者不必要地强制创建新的子外壳,而该子外壳可能会优化也可能不会优化。
注2:两种形式均假定不A
产生任何输出,在您的示例中这是正确的,但通常不一定如此。可以避免
A; if [ "$?" -eq 0 ]; then B; else C; fi | D
{ … }
不会由于管道而强制创建子外壳吗?我观察到以下行为:pgrep bash
和pgrep bash | cat
和if true; then pgrep bash; fi
并且{ pgrep bash; }
有一行输出;( pgrep bash; )
和( pgrep bash; ) | cat
和{ pgrep bash; } | cat
和if true; then pgrep bash; fi | cat
具有输出的两行。
... | ...
导致创建子壳,这是不可避免的。( ... )
,至少在理论上,导致额外的要创建子shell的是{ ...; }
避免了,但是这就是我的意思与“可能会或可能不会得到优化”:这是可能的,在这种特殊情况下,壳认识也没关系,该效果是一样的。
接受者的回答是正确的,但没有涵盖没有作为输出A
的输入的潜在用例D
。为此,您需要A
根据需要进行流重定向。
如果A
仍然要丢弃输出:
{ A >/dev/null && B || C; } | D
如果要A
在终端上查看输出:
{ A >/dev/tty && B || C; } | D
如果您需要输出A
作为后续命令的输入,则E
需要一个附加的命令组和流重定向:
{ { A >&3 && B || C; } | D; } 3>&1 | E
如果这一切看起来对您来说都不是一件容易的事(对我来说是如此),我建议您使用特殊的shell变量作为的退出状态A
并使用它:
A
if [ $? -eq 0 ]; then
B
else
C
fi |
D
如果您想更简洁但又不要太神秘,我建议这样做:
A; { [ $? -eq 0 ] && B || C; } | D
(另请参阅hvd答案的最后一部分,当我写原始答案时我没有注意到。)
A
从管道中移出。
A && (B || C) | D
,如果您不希望B在A失败时运行B,C或D