While循环 - 使用进程替换和命令替换的“here string”

12

有人能否解释一下这两个 while 循环的区别:

while read test; do
echo $test
done <<< "$(seq 5)"
while read test; do
echo $test
done < <(seq 5)

1
你看过 man bash 吗? - paxdiablo
2个回答

18
while read test; do
  echo $test
done <<< "$(seq 5)"

执行seq 5,将结果保存到一个临时变量中。然后执行while循环,将保存的结果作为输入。

while read test; do
  echo $test
done < <(seq 5)

建立一个子shell以执行seq 5,并将其stdout连接到stdin。然后启动while循环。完成时恢复stdin

有什么不同吗?对于seq 5,实际上没有什么区别;但是,可以通过将seq 5更改为seq 5; echo done generating sequence >&2来使其可见。然后您可以看到,在第一种情况下,整个seq执行完成后,while循环开始,而在第二种情况下,它们并行执行。

$ while read n; do echo $n > /dev/stderr; done \
>       <<<"$(seq 5; echo done generating sequence >&2)"
done generating sequence
1
2
3
4
5
$ while read n; do echo $n > /dev/stderr; done \
>       < <(seq 5; echo done generating sequence >&2)
1
2
done generating sequence
3
4
5

如果是seq 10000000,差异将更加明显。<<<"$(...)形式将使用更多的内存以存储临时字符串。


4
根据我的理解,唯一的区别在于过程替代会将命名管道(例如/dev/fd/63)表示为输入文件,而<<< ""会像读取缓冲区一样内部发送输入。当然,如果读取输入的命令在另一个进程中,例如子shell或另一个二进制文件,则会像管道一样将其发送到该进程。在无法使用“进程替换”(如Cygwin中),“此处文档”或“此处字符串”以及“命令替换”等环境中,有时更有帮助。
如果您执行echo <(:),则可以看到过程替代与其他字符串输入在概念上的区别。
过程替代更多地表示文件,而此处字符串更多地用于发送缓冲区以供输入使用。

1
你能解释一下为什么 echo <(:) 会以 /dev/fd/<number> 的形式打印文件吗? : 是一个特殊字符吗? - jmrah
2
为了后人,:字符是true命令的别名,似乎是展示进程替换最简洁的方式。有关:的更多信息,请参见此SO答案:https://dev59.com/unA75IYBdhLWcg3wkZ6A#3224910 - jmrah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接