piping stderr and stdout separately

2019-06-25 17:15发布

问题:

I'd like to do different things to the stdout and stderr of a particular command. Something like

cmd |1 stdout_1 | stdout_2 |2 stderr_1 | stderr_2

where stdout_x is a command specifically for stdout and stderr_x is specifically for stderr. It's okay if stderr from every command gets piped into my stderr commands, but it's even better if the stderr could be strictly from cmd. I've been searching for some syntax that may support this, but I can't seem to find anything.

回答1:

You can make use of a different file descriptor:

{ cmd 2>&3 | stdout_1; } 3>&1 1>&2 | stderr_1

Example:

{ { echo 'out'; echo >&2 'error'; } 2>&3 | awk '{print "stdout: " $0}'; } 3>&1 1>&2 |
  awk '{print "stderr: " $0}'
stderr: error
stdout: out

Or else use process substitution:

cmd 2> >(stderr_1) > >(stdout_1)

Example:

{ echo 'out'; echo >&2 'error'; } 2> >(awk '{print "stderr: " $0}') \
> >(awk '{print "stdout: " $0}')
stderr: error
stdout: out

to pipe stdout and stderr separately from your cmd.



回答2:

You can use process substitution and redirection to achieve this:

cmd 2> >(stderr_1 | stderr_2) | stdout_1 | stdout_2


回答3:

The most straightforward solution would be something like this:

(cmd | gets_stdout) 2>&1 | gets_stderr

The main drawback being that if gets_stdout itself has any output on stdout, that will also go to gets_stderr. If that is a problem, you should use one of anubhava's or Kevin's answers.



标签: bash shell