Bash – Process substitution with tee and paste

bashprocess-substitutiontee

I'm trying to pipe a command through the output of two other commands and then merge the results of the two process substitutions. An example that gets me close is:

command | tee >(sed -rn 's/.*foo (bar).*/1/p') >(awk '{print $3}')

However, I would like to achieve the following:

  • I don't need to see the input stream of the original command
  • I would like to use 'paste' to merge the results

I suppose one option is to run two separate commands and put them into files, but that isn't as elegant as I would like. What is the most elegant (single liner, clearly understood) way to do this in bash?

Best Answer

The reason you are seeing the output of the original command is because tee outputs to stdout as well as the files specified. To discard this you can put >/dev/null at the end of the command or redirect this output to one of your process substitutions by adding an extra >, eg:

command | tee >(sed -rn 's/.*foo (bar).*/1/p') > >(awk '{print $3}')

Or simpler just use another pipe:

command | tee >(sed -rn 's/.*foo (bar).*/1/p') | awk '{print $3}'

As for combining the result of the two process substitutions using paste, unless there is some obscure shell trick that I don't know about, there is no way to do this without using a named pipe. Ultimately this is two lines (formatted to more for clarity):

mkfifo /tmp/myfifo
command |
  tee >(sed -rn 's/.*foo (bar).*/1/p' >/tmp/myfifo) |
  awk '{print $3}' |
  paste /tmp/myfifo -

If you are putting this in a script, also consider using the recommendations for creating a temporary named pipe here.

Related Question