进程替换捕获stderr

10

对于这个问题,我将使用grep,因为它的使用文本会打印到stderr:

$ grep
Usage: grep [OPTION]... PATTERN [FILE]...
Try `grep --help' for more information.

你可以使用进程替代轻松捕获标准输出:

$ read b < <(echo hello world)

然而 stderr 会溜过进程替换并打印到控制台:

$ read b < <(grep)
Usage: grep [OPTION]... PATTERN [FILE]...
Try `grep --help' for more information.

我想使用进程替换来捕获stderr。我现在正在使用以下内容:

$ grep 2> log.txt

$ read b < log.txt

但我希望避免使用临时文件。

3个回答

15

将命令的标准错误重定向到标准输出:

$ read "b" < <(grep 2>&1)
$ echo "$b"
Usage: grep [OPTION]... PATTERN [FILE]...

虽然在 Bash 中将命令的输出保存到变量中的传统方法是使用 $()

$ b=$(grep 2>&1)
$ echo "$b"
Usage: grep [OPTION]... PATTERN [FILE]...
Try `grep --help' for more information.

也许他想要清除之前输出到stdout的内容,只捕获stderr?我是这样做的。 - Sandburg
read "b" < <(grep 2>&1) 只读取第一行到 $b 变量中,而 b=$(grep 2>&1) 会读取全部输出。 - finnan

2
$ grep 2> >(sed 's/e/E/g';)

你可以捕获 grep 的标准输出并将其管道传输到 sed,但是我不知道为什么(也不知道如何避免),它需要一个额外的 INTRO 来返回控制并显示提示符。 编辑: 你可以像这样修复不匹配:
$ grep 2> >(sed 's/e/E/g';); sync

2
你几乎是正确的。在你的进程替换中有一个不必要的;。这就是为什么你需要 ; sync 来解决这个问题。只需尝试:grep 2> >(sed 's/e/E/g'),你就会立即得到一个输出。 - John Goofy

1

对于整个子shell的更通用解决方案是使用exec重定向其标准错误。

如果,与OP基于grep的示例不同,您在子shell中有一系列命令,则可以像这样重定向整个子shell的标准错误:

b=$(cat <(
    exec 2>&1
    echo "standard output"
    echo "standard error" 1>&2
   ))    

echo $b

这将标准输出和标准错误输出放入变量$b中:

standard output standard error

"echo语句只是输出内容到标准输出和标准错误流的示例。"

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