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)'
产生错误。
任何想法为什么?
答案 0 :(得分:21)
注意: <filename
不是进程替换。这是一个redirection。流程替换的格式为<(command)
。
流程替换替换了<(...)
的进程的名称。尽管使用了&lt; 符号,但它不是重定向。
因此,当您说cat <(echo foo)
时,bash会创建一个子进程来运行echo
命令,并替换可以读取的伪文件的名称以获取该命令的输出。替换的结果将是这样的:
cat /dev/fd/63
请注意,没有重定向。 (您可以通过键入echo <(echo foo)
来查看此操作。)
与许多实用程序一样,可以使用或不使用命令行参数调用cat
;如果未指定文件,则从stdin
读取。因此cat file.txt
和cat < 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将继续支持当前的表示法。