为什么进程替换并不总是与bash中的while循环一起使用?

时间:2015-03-08 13:49:09

标签: bash process while-loop substitution

process substitution适用于文件名,例如两个

$ cat <FILENAME

$ while read i; do echo $i; done <FILENAME

的工作。

但是如果我们使用echo命令(或任何其他产生输出到stdout的命令)代替FILENAME,cat继续工作

$ cat <(echo XXX)
XXX
循环时

$ while read i; do echo $i; done <(echo XXX) 
bash: syntax error near unexpected token `<(echo XXX)'

产生错误。

任何想法为什么?

3 个答案:

答案 0 :(得分:21)

注意: <filename 不是进程替换。这是一个redirection。流程替换的格式为<(command)

流程替换替换了<(...)的进程的名称。尽管使用了&lt; 符号,但它不是重定向。

因此,当您说cat <(echo foo)时,bash会创建一个子进程来运行echo命令,并替换可以读取的伪文件的名称以获取该命令的输出。替换的结果将是这样的:

cat /dev/fd/63

请注意,没有重定向。 (您可以通过键入echo <(echo foo)来查看此操作。)

与许多实用程序一样,可以使用或不使用命令行参数调用cat;如果未指定文件,则从stdin读取。因此cat file.txtcat < file.txt非常相似。

但是while命令不接受其他参数。所以

while read -r line; do echo "$line"; done < file.txt 

有效,但

while read -r line; do echo "$line"; done file.txt

是语法错误。

流程替换不会改变这一点。所以

while read -r line; do echo "$line"; done /dev/fd/63

是语法错误,因此也是

while read -r line; do echo "$line"; done <(echo foo)

要指定流程替换的重定向,您需要重定向:

while read -r line; do echo "$line"; done < <(echo foo)

请注意,两个&lt; 符号之间必须有空格,以避免与“here-doc”语法<<word混淆。

答案 1 :(得分:2)

我为愚蠢而道歉,只是找到了可行的解决方案

$ while read i; do echo $i; done < <(echo XXX)
XXX

如果有人能用双重减号< <来解释这个奇怪语法背后的想法,我将非常感激。

答案 2 :(得分:1)

进程替换操作会生成一个文件名,通常在/dev/fd中,但并非强制要求。需要用这些术语来思考;它可以在可以使用文件名的地方使用。

您可以看到它的用途,例如:

echo <(cat /etc/passwd)

您的示例显示了这一点。 cat命令接受文件名参数。 done关键字不接受文件名参数,但接受I / O重定向。

你可以认定这种符号令人困惑;在某些方面,它是。但抱怨没什么意义。这就是Bash的做法。您可以使用不同的表示法创建自己的shell,但是由于向后兼容性原因,Bash将继续支持当前的表示法。