Explanation
Regarding the command line, replacing a process is just a way to create a special file name. (See also docs .) Thus, the second pipeline looks like this:
printf 'abcd\nl33t\n1234\n' | tee /dev/fd/nn | grep '[0-9]'
where nn is the descriptor file number. The full output of printf goes to /dev/fd/nn , and also goes to grep '[0-9]' . Therefore, only numerical values ββare printed.
As for the process inside >() , it inherits stdout of its parent. In this case, this stdout is inside the pipe. Therefore, the output of grep '[az]' passes through the pipeline in the same way as the standard output of tee . As a result, the pipeline as a whole skips only lines containing numbers.
When you write instead of stderr ( >&2 ), you bypass the last stage of the pipeline. Therefore, the output of grep '[az]' on stderr is sent to the terminal.
Fix
To fix this without using stderr, you can use a different alias for your screen. For instance:.
printf 'abcd\nl33t\n1234\n' | tee >(grep '[az]' >/dev/tty ) | grep '[0-9]'
which gives me a way out
l33t 1234 abcd l33t
Testing this
To sort this, I ran echo >(ps) . The ps process was a child of the bash process executing the pipeline.
I also ran
printf 'abcd\nl33t\n1234\n' | tee >(grep '[az]')
without | grep '[0-9]' | grep '[0-9]' at the end. In my system, I see
abcd <--- the output of the tee l33t ditto 1234 ditto abcd <-- the output of the grep '[az]' l33t ditto
All five lines are in grep '[0-9]' .