【问题标题】:Difference between x | y and y <(x) in bash?x之间的区别| bash 中的 y 和 y <(x)?
【发布时间】:2016-07-15 18:40:18
【问题描述】:

command1 | command2 和 command2 &lt;(command1) 有区别吗?

例如,git diff | more 与 more &lt;(git diff)

我的理解是两者都采用command2 的标准输出并将其通过管道传输到command1 的标准输入。

【问题讨论】:

    标签: bash pipe


    【解决方案1】:

    主要区别在于&lt;(...),称为“进程替换”,由shell 转换为作为常规参数传递给命令的文件名;它不会向命令的标准输入发送任何内容。这意味着它不能直接与诸如 tr 之类的不带文件名参数的命令一起使用:

    $ tr a-z A-Z <(echo hello)
    usage: tr [-Ccsu] string1 string2
           tr [-Ccu] -d string1
           tr [-Ccu] -s string1
           tr [-Ccu] -ds string1 string2
    

    但是,您始终可以在 &lt;(...) 前面放置另一个 &lt; 以将其转换为输入重定向:

    $ tr a-z A-Z < <(echo hello)
    HELLO 
    

    而且因为它会生成一个文件名,所以您可以使用带有多个文件参数的命令进行进程替换:

    $ diff -u <(echo $'foo\nbar\nbaz') <(echo $'foo\nbaz\nzoo')
    --- /dev/fd/63  2016-07-15 14:48:52.000000000 -0400
    +++ /dev/fd/62  2016-07-15 14:48:52.000000000 -0400
    @@ -1,3 +1,3 @@
     foo
    -bar
     baz
    +zoo
    

    另一个显着的区别是管道创建的子壳在父环境中不会产生副作用:

     $ echo hello | read x
     $ echo $x
     # nothing - x is not set
    

    但是使用进程替换,只有括号内的进程在子shell中;周围的命令仍然会产生副作用:

     $ read x < <(echo hello)
     $ echo $x
     hello
    

    值得一提的是,您也可以使用&gt;(...) 写入进程,尽管这样有用的情况较少:

    $ echo hello > >(cat)
    hello
    

    【讨论】:

    • 哦,这真的很酷!感谢您的回复,完美回答了我的问题。
    【解决方案2】:

    a | b 从可执行文件 a 获取 stdout 输出并将其作为 b 的 stdin 提供给可执行文件 b。

    a &gt; b 从可执行文件a 中获取stdout,并将其重定向/写入文件b。

    a &lt; b 获取文件b 的内容并将其重定向/输入到可执行文件a 作为其stdin

    换句话说,| 管道输出在程序之间,而&lt; 和&gt; 管道文件进入/退出程序。

    您的带有() 的版本运行一个额外的过程,同时完成基本相同的事情。

    【讨论】:

    • 否; &lt;(…) 符号与您描述的不同!它生成一个文件名;要从中重定向,您需要 &lt; &lt;(…) — 或 &gt; &gt;(…) 进行输出重定向。
    • 感谢您的回复,但 a gnu.org/software/bash/manual/bashref.html#Process-Substitution)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-31
    • 1970-01-01
    • 2012-10-07
    • 1970-01-01
    • 2011-02-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多