管道 STDERR 与 STDOUT

Naf*_*Kay 26 bash pipe io-redirection

根据“ Linux: The Complete Reference 6th Edition ”(第 44 页),您只能使用|&重定向符号通过管道传输 STDERR 。

我写了一个非常简单的脚本来测试这个:

#!/bin/bash
echo "Normal Text."
echo "Error Text." >&2
Run Code Online (Sandbox Code Playgroud)

我像这样运行这个脚本:

./script.sh |& sed 's:^:\t:'
Run Code Online (Sandbox Code Playgroud)

据推测,只有打印到 STDERR 的行才会缩进。但是,正如我所见,它实际上并不是这样工作的:

    Normal Text.
    Error Text. 
Run Code Online (Sandbox Code Playgroud)

我在这里做错了什么?

Gil*_*il' 28

我不知道你的书使用了什么文本,但bash 手册很清楚(如果你已经有点熟悉重定向):

如果|&使用,command1的标准错误,除了它的标准输出,通过管道连接到command2的标准输入;它是 的简写2>&1 |。标准错误到标准输出的这种隐式重定向是在命令指定的任何重定向之后执行的。

因此,如果您不想混合标准输出和标准错误,则必须将标准输出重定向到其他地方。请参阅如何 grep 标准错误流 (stderr)?

{ ./script.sh 2>&1 >&3 | sed 's:^:\t:'; } 3>&1
Run Code Online (Sandbox Code Playgroud)

但是,script.sh和的fd 1 和 3 都sed将指向原始标准输出目的地。如果你想成为一个好公民,你可以关闭那些命令不需要的那些 fd 3:

{ ./script.sh 2>&1 >&3 3>&- | sed 's:^:\t:' 3>&-; } 3>&1
Run Code Online (Sandbox Code Playgroud)

bash并且ksh93可以压缩>&3 3>&->&3-(fd move)。

  • @sxc731 `|&` 是 `2>&1 |` 的简写。因此 `>/tmp/stdout_goes_here |&` 将 stdout 重定向到 `/tmp/stdout_goes_here`,然后 `2>&1` 将 stderr 重定向到 stdout 所在的位置,即 `/tmp/stdout_goes_here`,最后 `|` 则不会'无法接收任何输入,因为命令的输出已被重定向。请记住,`>&1` 重定向到_文件描述符 1 当前所在的位置_,而不是_文件描述符 1 最终将到达的位置_。要仅通过管道传输 stderr 并将 stdout 重定向到文件,一种方法是“2>&1 >/tmp/stdout_goes_here |”。 (2认同)

Kev*_*vin 8

|&将 stderr 管道到 stdin,例如2>&1 |,因此下一个程序将在 stdin 上获取两者。

$cat test.sh
#!/bin/bash
echo "Normal Text."
echo "Error Text." >&2
$./test.sh | sed 's:^:\t:'
Error Text.
        Normal Text.
$ ./test.sh |& sed 's:^:\t:'
        Normal Text.
        Error Text.
Run Code Online (Sandbox Code Playgroud)