在 bash 中通过管道传输 stdout 和 stderr?

问题描述 投票:0回答:3

似乎较新版本的 bash 有

&>
运算符,它(如果我理解正确的话)将 stdout 和 stderr 重定向到一个文件(
&>>
附加到文件,而不是附加到文件,正如 Adrian 所澄清的那样)。

实现相同目标但通过管道传输到另一个命令的最简单方法是什么?

例如,在这一行中:

cmd-doesnt-respect-difference-between-stdout-and-stderr | grep -i SomeError

我希望 grep 能够匹配 stdout 和 stderr 中的内容(实际上,将它们组合成一个流)。

注意:这个问题询问的是管道,不是重定向 - 所以它不是当前标记为重复的问题的重复。

bash stdout stderr piping
3个回答
239
投票

(请注意,

&>>file
追加到文件,而
&>
将重定向并覆盖以前存在的文件。)

要组合

stdout
stderr
,您可以使用
1>&2
将后者重定向到前者。这会将 stdout(文件描述符 1)重定向到 stderr(文件描述符 2),例如:

$ { echo "stdout"; echo "stderr" 1>&2; } | grep -v std
stderr
$

stdout
转到标准输出,
stderr
转到标准错误。
grep
只能看到
stdout
,因此
stderr
会打印到终端。

另一方面:

$ { echo "stdout"; echo "stderr" 1>&2; } 2>&1 | grep -v std
$

写入 stdout 和 stderr 后,

2>&1
将 stderr 重定向回 stdout,并且
grep
在 stdin 上看到这两个字符串,从而过滤掉这两个字符串。

您可以在此处阅读有关重定向的更多信息。

关于您的示例(POSIX):

cmd-doesnt-respect-difference-between-stdout-and-stderr 2>&1 | grep -i SomeError

或者,使用

>=bash-4
:

cmd-doesnt-respect-difference-between-stdout-and-stderr |& grep -i SomeError

203
投票

Bash 4.0 及更高版本有

2>&1 |
的简写形式,即
|&
,它可以通过管道传输 stdout 和 stderr(请参阅 手册):

cmd-doesnt-respect-difference-between-stdout-and-stderr |& grep -i SomeError

有关引入此功能的详细信息,请参阅 Bash 发行说明。请注意,macOS 附带的默认 Bash 早于 4.0,因此支持简写。


3
投票

如果您想将 STDOUT 和 STDERR 传输到 different 子 shell,而不是两者都传输到同一个子 shell(如

|&
/
2>&1
所做的那样),我使用这个:

producer \
  >  >( stdout_pipeline... ) \
  2> >( stderr_pipeline... ) \
  ...

虽然这使用了重定向运算符,但它使用底层的管道将生产者连接到子 shell。

您可以通过这种方式处理多个输出流(2不是限制),也可以使用企鹅运算符(

[n]< <(...)
)以类似的方式从子shell传输(可能是多个)输入流。

© www.soinside.com 2019 - 2024. All rights reserved.