【问题标题】:Portable way of getting a fd filename of a commnd stdout in a shell script在 shell 脚本中获取命令 stdout 的 fd 文件名的便携式方法
【发布时间】:2014-08-02 11:17:53
【问题描述】:

我很确定我缺少这方面的术语,这可能是谷歌让我失望的原因。是否有一种可移植且简单的方法将标准输出重定向到多个命令。

换句话说,我该如何解决这个可移植性问题:

$ /bin/bash -c '(echo to your mom) | tee >(read b; echo "agent 1 reports $b") >(read b; echo "agent 2 reports $b")  >(read b; echo "agent 3 reports $b")'
to your mom
agent 1 reports to your mom
agent 2 reports to your mom
agent 3 reports to your mom
$ /bin/zsh -c '(echo to your mom) | tee >(read b; echo "agent 1 reports $b") >(read b; echo "agent 2 reports $b")  >(read b; echo "agent 3 reports $b")'
to your mom
agent 1 reports to your mom
agent 3 reports to your mom
agent 2 reports to your mom
$ /bin/sh -c '(echo to your mom) | tee >(read b; echo "agent 1 reports $b") >(read b; echo "agent 2 reports $b")  >(read b; echo "agent 3 reports $b")'
/bin/sh: 1: Syntax error: "(" unexpected

请注意,输出排序不是问题,/bin/sh 产生错误是问题。

【问题讨论】:

    标签: shell unix pipe portability file-descriptor


    【解决方案1】:

    使用命名管道:

    #!/bin/sh
    
    fifo1=$(exec mktemp --dry-run)
    mkfifo "$fifo1"
    ( read b; echo "agent 1 reports $b" ) < "$fifo1" &
    
    fifo2=$(exec mktemp --dry-run)
    mkfifo "$fifo2"
    ( read b; echo "agent 2 reports $b" ) < "$fifo2" &
    
    fifo3=$(exec mktemp --dry-run)
    mkfifo "$fifo3"
    ( read b; echo "agent 3 reports $b" ) < "$fifo3" &
    
    echo to your mom | tee "$fifo1" "$fifo2" "$fifo3"
    
    rm -f "$fifo1" "$fifo2" "$fifo3"
    

    用法:

    sh script.sh
    

    输出:

    to your mom
    agent 2 reports to your mom
    agent 1 reports to your mom
    agent 3 reports to your mom
    

    这就是科学。并且通过功能,您可以根据自己的喜好使用技术来简化管道。

    【讨论】:

    • 酷!,您是否认为可以取消命名管道并以某种方式使用文件描述来简洁?
    • @fakedrake 使用普通的外壳你可能无法做到这一点。您可以使用普通 shell 创建的唯一管道是通常的管道 |
    猜你喜欢
    • 1970-01-01
    • 2010-12-21
    • 2013-09-03
    • 2011-01-26
    • 2017-12-24
    • 1970-01-01
    • 2011-04-06
    • 2023-04-08
    • 1970-01-01
    相关资源
    最近更新 更多