所以,我希望将 的输出unzip -Z1
放入数组中并找到了这个答案;他们的第一个选择,使用mapfile
输入重定向并处理替换,很有魅力。
但后来我想,“等等,进程替换”,它从标准输出创建一个文件描述符,“然后使用输入重定向将内容放入标准输入?”
这不等同于管道吗?
显然没有。不,不是。在这里,我尝试将 的内容ls
放入变量中,但使用的是管道:à la ls | mapfile -t test
Nada。
但是,如果我按照 T 的答案:id est mapfile -t test < <(ls)
Voilà。
除了创建文件描述符外,我找不到任何内在的特殊之处。< <()
以此为理论,我尝试了 HEREDOC,它也制作了一个文件描述符。有效:
mapfile -t test2 << END && printf '%s ' "${test2[@]}"
this
is
an
array
END
但如果它是通过stdin
via清洗的cat
,请尝试:
cat << END | mapfile -t test3 && printf '%s ' "${test3[@]}"
this
is
an
array
END
所以,我的问题。
HEREDOC 发现/文件描述符理论应该无关紧要,mapfile
因为它的手册都说它使用“标准输入”,对吗?
如果“标准输入”以某种方式意味着它必须是一个更高级的描述符;为什么?为什么不能使用简单的一次读取输入流来生成数组?
最后,如果这两个都得到了回答/在正确的轨道上,为什么命令在预期 fd 时没有失败?你会看到我的终端0
打印了一堆(我们用&&
在最后一个例子中),那是$?
在我的上prompt
,所以内置没有报告错误。
我在 Fedora 30 和 RHEL 6 上试过这个,所以我不认为这是一个错误。
有用; 只是结果立即消失了。
不同之处在于,这
foo | mapfile
是一个由两个新进程组成的管道——每个元素,无论是外部程序还是内置 shell,都在子 shell 中运行。因此,尽管 mapfile 仍在执行其工作,但它无法将结果传输到父 shell 进程。为了进行比较,使用
(mapfile < foo.txt)
orls | while read line; do ... done
或 even会得到相同的结果(foo=bar); echo $foo
。在所有这些情况下,如果比较 $BASHPID 和 $$,您会看到不同的值——前者显示子 shell 进程 PID 与主 shell PID 不同。使用重定向时,该
mapfile
命令在主 shell 进程中运行,并且可以正确更改 shell 变量。它不太关心它是从真实文件、生成的<<
临时文件还是生成的<()
魔术文件进行重定向——在这种情况下,shell 将其作为一个单独的步骤处理,不会导致管道待建。<()
(当然, or的内部命令$()
是一个子 shell。)请注意,该变量实际上可以在子 shell 中使用——只是不能向上传输。因此,对于一次性操作,管道的第二部分可能会非常复杂: