代码之家  ›  专栏  ›  技术社区  ›  Martin DeMello

通过过滤器的管道

  •  63
  • Martin DeMello  · 技术社区  · 14 年前

    在bash中,在将STDERR与STDOUT统一之前,是否有任何方法可以通过一个过滤器对其进行管道传输?也就是说,我想

    STDOUT ────────────────┐
                           ├─────> terminal/file/whatever
    STDERR ── [ filter ] ──┘
    

    而不是

    STDOUT ────┐
               ├────[ filter ]───> terminal/file/whatever
    STDERR ────┘
    
    7 回复  |  直到 6 年前
        1
  •  65
  •   evandrix    9 年前

    how to swap file descriptors in bash

    STDERR: stderr output
    STDOUT: more regular
    
    ./a.out 3>&1 1>&2 2>&3 3>&- | sed 's/e/E/g'
    more regular
    stdErr output
    

    引用上述链接:

    1. 下一个发送stdout到stderr(&2被复制到1)
    2. 将stderr发送到&3(stdout)(&3被复制到2)
    3. 关闭&3(将&复制为3)
        2
  •  33
  •   Community CDub    5 年前

    TL;DR:

    $ cmd 2> >(stderr-filter >&2)
    

    例子:

    % cat /non-existant 2> >(tr o X >&2)
    cat: /nXn-existant: NX such file Xr directXry
    %
    

    sh see here .


    解释

    到目前为止,最简单的方法是通过 process substitution :

    进程替换允许使用文件名引用进程的输入或输出。它的形式是

    >(list)
    

    进程列表以异步方式运行,其输入或输出显示为文件名。

    就像你可以做的:

    $ cmd 2> filename
    

    你能做到的

    $ cmd 2> >(filter >&2)
    

    >&2 重定向的 filter 回到原来的标准。

        3
  •  24
  •   solidsnack    12 年前

    简单地使用进程替换似乎可以过滤 stderr 与…分开 stdout

    :; ( echo out ; echo err >&2 ) 2> >( sed s/^/e:/ >&2 )
    out
    e:err
    

    请注意 标准错误 出现在 标准错误 标准 标准 ,我们可以通过将整个内容包装到另一个子shell并重定向到文件来查看 o e

    ( ( echo out ; echo err >&2 ) 2> >( sed s/^/e:/ >&2 ) ) 1>o 2>e
    
        4
  •  16
  •   Community CDub    5 年前

    TL;DR:(bash和zsh)

    $ cmd 2> >(stderr-filter >&2)
    

    例子:

    % cat /non-existant 2> >(tr o X >&2)
    cat: /nXn-existant: NX such file Xr directXry
    %
    

    cat /non-existant 3>&1 1>&2 2>&3 3>&- | sed 's/e/E/g'
    

    这有一个内置的假设:文件描述符3没有用于其他用途。

    相反,使用命名文件描述符,然后 {ba,z}sh 将分配下一个可用的文件描述符>=10:

    cat /non-existant {tmp}>&1 1>&2 2>&$tmp {tmp}>&- | sed 's/e/E/g'
    

    sh .

    允许POSIX中的向前管道 gets complicated :

    (cmd 2>&1 >&3 3>&- | stderr-filter >&2 3>&-) 3>&1
    

    因此,考虑到这一假设和复杂的语法,使用更简单的 bash zsh 语法显示在TL;DR上面,并解释 here .

        5
  •  8
  •   Pecunifex    12 年前

    $ cat ./p
    echo stdout
    echo stderr >&2
    $ ./p 2> >(sed -e 's/s/S/') | sed 's/t/T/'
    sTdout
    STderr
    

    仅将第一个sed命令用作stderr上的筛选器,并使用第二个sed命令修改联接的输出。

    请注意,2>之后的空格是命令正确解析的必需空格。

        6
  •  5
  •   tripleee    8 年前

    this page 《高级Bash脚本指南》的第二部分是“仅将stderr重定向到管道”。

    #仅将stderr重定向到管道。

    exec 3>&1                              # Save current "value" of stdout.
    ls -l 2>&1 >&3 3>&- | grep bad 3>&-    # Close fd 3 for 'grep' (but not 'ls').
    #              ^^^^   ^^^^
    exec 3>&-                              # Now close it for the remainder of the script.
    

    这也许就是你想要的。如果没有,ABSG的其他部分应该可以帮助你,这是极好的。

        7
  •  3
  •   wilhelmtell    14 年前

    $ mkfifo err
    $ cmd1 2>err |cat - err |cmd2