cmd | read -r var1 var2
众所周知,该构造在 bash 中不起作用,因为由于管道,读取命令在子 shell 中执行。我曾经用来read -r var1 var2 <<< "$(cmd)"
解决这个问题,但最近我了解了这个cmd_drain < <(cmd_src)
结构,它似乎也能正常工作:read -r var1 var2 < <$(cmd)
.
这两种解决方案有区别吗?虽然目前没有似乎是在平凡的情况下,任何的区别:
$ hd < <(echo Hello)
00000000 48 65 6c 6c 6f 0a |Hello.|
00000006
$ hd <<< $(echo Hello)
00000000 48 65 6c 6c 6f 0a |Hello.|
00000006
Run Code Online (Sandbox Code Playgroud)
我还尝试了一些特殊字符并得到了相同的结果。我的直觉是,结果总是相同的,即在cmd_drain <<< "$(cmd_src)"
将cmd_src
整个结果提供给它之前首先运行并在内存中缓冲整个结果cmd_drain
,同时cmd_drain < <(cmd_src)
将继续提供cmd_src
into的输出cmd_drain
。我认为它像cmd_src | cmd_drain
除了cmd_src
将在运行子shell来代替cmd_drain
。我的假设正确吗?
额外的问题:在$()
构造周围是否需要引用?
Olo*_*rin 10
是的,你的假设是正确的。在cmd_drain < <(cmd_src)
(又名Process Substitution,结合正常重定向)中,Bash 将替换<(cmd_src)
为文件的路径,从中cmd_src
可以读取的输出。从文档:
进程列表异步运行,其输入或输出显示为文件名。这个文件名作为扩展的结果作为参数传递给当前命令。如果使用
>(list)
表单,写入文件将为列表提供输入。如果使用<(list)
表单,则应读取作为参数传递的文件以获得列表的输出。
在cmd_drain <<< "$(cmd_src)"
, <<< ...
被视为任何其他here-string,因此:
单词经历波浪号扩展、参数和变量扩展、命令替换、算术扩展和引号删除。不执行路径名扩展和分词。结果作为单个字符串提供,并附加一个换行符,在其标准输入 [...]
所以你不需要在$()
那里引用,但特别是因为这里的字符串<<<
语法不进行分词或文件名扩展。通常,你必须这样做。
再次注意此处字符串文档的最后一句 - 附加了换行符:
bash-5.0$ od -c <<< $(printf %s foo)
0000000 f o o \n
0000004
bash-5.0$ od -c < <(printf %s foo)
0000000 f o o
0000003
Run Code Online (Sandbox Code Playgroud)
这是否重要取决于您正在运行的内容。
在 中hd <<< $(echo Hello)
,命令替换删除了尾随的换行输出echo
,here 字符串添加了一个换行符,从而有效地为您提供相同的输出。但是,如上面的示例所示,这种删除/添加换行符可能很棘手,而且您不需要确切地获得什么cmd_src
输出。
归档时间: |
|
查看次数: |
372 次 |
最近记录: |