管道 STDERR 与 STDOUT

管道 STDERR 与 STDOUT

根据 ”Linux:完整参考第 6 版“(第 44 页),你可以用管道仅有的STDERR 使用|&重定向符号。

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

#!/bin/bash
echo "Normal Text."
echo "Error Text." >&2

我像这样运行这个脚本:

./script.sh |& sed 's:^:\t:'

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

    Normal Text.
    Error Text. 

我在这里做错了什么?

答案1

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

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

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

{ ./script.sh 2>&1 >&3 | sed 's:^:\t:'; } 3>&1

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

{ ./script.sh 2>&1 >&3 3>&- | sed 's:^:\t:' 3>&-; } 3>&1

bashksh93可以压缩>&3 3>&-to >&3-(fd move)。

答案2

|&将 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.

答案3

|&在 bash 中只是 的一个(不太可移植)快捷方式2>&1 |,因此您应该看到每一行都缩进。

相关内容