bash正向流程替换背后发生了什么?

时间:2013-04-17 21:44:46

标签: bash process

根据维基百科的说法,“进程替换也可用于捕获通常发送到文件的输出,并将其重定向到进程的输入。”(http://en.wikipedia.org/wiki/Process_substitution)。

所以,用我自己的话说,这意味着通过进程替换,我可以获取命令A的输出并将其用作命令B的输入。换句话说,它就像一个管道(这是正确的吗?)

如果这是真的,如果我这样做:

echo "test" >(wc)

然后我应该得到以下结果:

1 1 5

因为我对上述命令的理解类似于以下内容:

$echo "test" > tmp
$wc tmp
1 1 5 tmp

除了我没有使用进程替换生成tmp文件。

但我得到以下输出:

test /dev/fd/63

这显然表明我的心理模型不正确。我哪里错了?

我理解<(命令)。例如

$diff <(head file1) <(head file2) 

完全有道理。但不是&gt;(命令)。

2 个答案:

答案 0 :(得分:3)

来自Process Substitution

  

进程列表运行时其输入或输出连接到 FIFO或 / dev / fd 中的某个文件。 作为扩展的结果,此文件的名称作为参数传递给当前命令。如果使用&gt;(列表)表单,写入文件将为列表提供输入

echo "test" >(wc)会怎样?

文件/dev/fd/63已打开,可将echo testwc联系起来。 wc启动时,其输入已连接到/dev/fd/63。然后将此文件的名称(/dev/fd/63)作为参数传递给当前命令(echo "test"),从而生成echo "test" /dev/fd/63。这就是你看到

的原因
test /dev/fd/63

作为输出。 wc等待输入,但由于echo未写入/dev/fd/63,因此计数将为0

如果你希望这个工作,你必须创建一个脚本,它接受最后一个参数并将第一个N-1参数回显到最后一个

#! /bin/bash
echo "${@:1:$(($# - 1))}" >${@: -1}

当你打电话给这个

bash script.sh test >(wc)

您将看到预期的输出

1 1 5

答案 1 :(得分:2)

您的心理模型不正确,因为您错过了一个重要细节:流程替换不是重定向。

执行重定向时,例如&#34; echo test&gt; tmp&#34;,执行的是&#34; echo test&#34;,并且stdout(由&#34;&gt;&#34;表示)被定向到名为&#34; tmp&的文件中#34 ;.当您执行替换时,例如&#34; echo test&gt;(wc)&#34;,&#34; wc&#34;执行,&#34;&gt;(wc)&#34;被可以读取或写入的文件名(或可能是魔法设备的名称)取代​​。

引自您链接到的维基百科页面:&#34;在引擎盖下,进程替换通过创建命名管道,然后在命令行上替换其名称来工作。&#34;

如果仔细观察&#34;差异&#34;上面的示例,您也会看到它,它的工作方式相同。毕竟,&#34; diff&#34;的论点是什么?但命令行上的文件名?