For this question I will use grep, because its usage text prints to stderr:

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

You can capture stdout easily with process substitution:

$ read b < <(echo hello world)

However stderr slips past the process substitution and prints to the console:

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

I would like to capture stderr using process substitution. I am using this now:

$ grep 2> log.txt

$ read b < log.txt

but I am hoping to avoid the temp file.

有帮助吗?

解决方案

Redirect the stderr of your command to stdout:

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

Though the conventional way to save the output of a command to a variable in Bash is by using $():

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

其他提示

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

You can capture grep's stdout and pipe it to sed but, I don't know why (nor how to avoid it) it needs an extra INTRO to return control and display the prompt.

Edit: You can fix that mismatch like this:

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

A more general solution for a whole subshell is to use exec to redirect its standard error.

If, instead of the OP's example based on grep being a single command, you had a sequence of commands in the subshell then you can redirect the standard error of the whole subshell like this:

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

echo $b

which puts the output of standard output and standard error into the variable $b:

standard output standard error

The echo statements are just examples to output something to each of standard output and standard error.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top