【问题标题】:piping stderr and stdout separately分别管道 stderr 和 stdout
【发布时间】:2015-01-10 20:56:15
【问题描述】:

我想对特定命令的 stdout 和 stderr 做不同的事情。类似的东西

cmd |1 stdout_1 | stdout_2 |2 stderr_1 | stderr_2

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

【问题讨论】:

    标签: bash shell


    【解决方案1】:

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

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

    示例:

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

    或者使用进程替换

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

    示例:

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

    从您的cmd分别管道 stdout 和 stderr。

    【讨论】:

    • 那么,在你的任何一个演示中,stderr_1 的输出都是普通的标准输出,对吧?
    • 检查我上面的示例,其中 stdout 和 stderr 在整个命令行中保持独立。
    • 对,我假设进程替换也是如此?
    • 是否依赖于进程替换顺序?即cmd 2> >(stderr_1) > >(stdout_1) cmd > >(stdout_1) 2> >(stderr_1)?
    • 是的,它是订单相关,否则stderr_1 的输出也会通过管道传输到stdout_1。所以最好先管道stderr,然后再管道stdout。 (如上图)
    【解决方案2】:

    您可以使用进程替换和重定向来实现此目的:

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

    【讨论】:

    • 那么 stderr_2 中的任何一个都是普通的标准输出,对吧?
    • 是的,一旦输出达到stderr_1 作为输入,它就会回到正常的管道。
    • stderr_2 的输出是否会进入stdout_1
    • 是的,stderr 管道结束后,进入stdout。但是你可以重定向到一个文件或 /dev/null 如果你不希望它在那里
    【解决方案3】:

    最直接的解决方案是这样的:

    (cmd | gets_stdout) 2>&1 | gets_stderr
    

    主要缺点是如果gets_stdout 本身在标准输出上有任何输出,那也将转到gets_stderr。如果这是一个问题,您应该使用 anubhava 或 Kevin 的答案之一。

    【讨论】:

    • 如果来自gets_stdout 的标准输出不打算转到gets_stderr,请将其标准输出重定向到一个文件,或者/dev/null 如果你真的不想看到它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-30
    • 2021-12-04
    • 1970-01-01
    • 2015-06-21
    • 1970-01-01
    • 2016-03-15
    相关资源
    最近更新 更多