Bash 管道标准件和标准件分开

Bash 管道标准件和标准件分开,bash,shell,Bash,Shell,我希望对特定命令的stdout和stderr执行不同的操作。差不多 cmd |1 stdout_1 | stdout_2 |2 stderr_1 | stderr_2 其中,stdout_x是专门用于stdout的命令,而stderr_x是专门用于stderr的命令。如果来自每个命令的stderr都通过管道传输到我的stderr命令中,这没关系,但是如果stderr可以严格地来自cmd,那就更好了。我一直在搜索一些可能支持这一点的语法,但似乎找不到任何东西。您可以使用进程替换和重定向来实现这一

我希望对特定命令的stdout和stderr执行不同的操作。差不多

cmd |1 stdout_1 | stdout_2 |2 stderr_1 | stderr_2

其中,stdout_x是专门用于stdout的命令,而stderr_x是专门用于stderr的命令。如果来自每个命令的stderr都通过管道传输到我的stderr命令中,这没关系,但是如果stderr可以严格地来自
cmd
,那就更好了。我一直在搜索一些可能支持这一点的语法,但似乎找不到任何东西。

您可以使用进程替换和重定向来实现这一点:

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

您可以使用不同的文件描述符:

{ cmd 2>&3 | stdout_1; } 3>&1 1>&2 | stderr_1
cmd 2> >(stderr_1) > >(stdout_1)
示例:

{ { echo 'out'; echo >&2 'error'; } 2>&3 | awk '{print "stdout: " $0}'; } 3>&1 1>&2 |
  awk '{print "stderr: " $0}'
stderr: error
stdout: out
{ echo 'out'; echo >&2 'error'; } 2> >(awk '{print "stderr: " $0}') \
> >(awk '{print "stdout: " $0}')
stderr: error
stdout: out
或者使用过程替换

{ cmd 2>&3 | stdout_1; } 3>&1 1>&2 | stderr_1
cmd 2> >(stderr_1) > >(stdout_1)
示例:

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

要将stdout和stderr分别从
cmd

中导入,最简单的解决方案如下:

(cmd | gets_stdout) 2>&1 | gets_stderr

主要的缺点是,如果
gets\u stdout
本身在stdout上有任何输出,那么也会转到
gets\u stderr
。如果这是一个问题,您应该使用anubhava或Kevin的答案。

那么,在您的两个演示中,stderr_1的结果都是在普通的旧stdout中,对吗?请检查我上面的示例,其中stdout和stderr在整个命令行中保持独立。对,我假设过程替换也是如此?过程替换顺序依赖吗?i、 e.
cmd 2>>(stderr_1)>>(stdout_1)
cmd>>(stdout_1)2>>(stderr_1)
?是的,它取决于顺序,否则
stderr_1
的输出也会通过管道传输到
stdout_1
。因此,最好先使用stderr,然后再使用stdout。(如上所示)那么,在这两种情况下,stderr_2的输出都是在普通的旧stdout中,对吗?是的,一旦输出作为输入命中
stderr_1
,它就返回到正常的管道。
stderr_2
的输出是否然后进入
stdout_1
?是的,在stderr管道结束后,它进入stdout。但是,如果
的标准输出不是要转到
的gets\u stdout
,则可以重定向到一个文件或/dev/null(如果您不想看到它),或者
/dev/null(如果您确实不想看到它),则可以重定向到该文件或/dev/null(如果您不想看到它)。