当我使用 时,我无法追加到数组parallel
,使用 for 循环没有问题。
并行示例:
append() { arr+=("$1"); }
export -f append
parallel -j 0 append ::: {1..4}
declare -p arr
输出:
-bash: declare: arr: not found
对于循环:
for i in {1..4}; do arr+=("$i"); done
declare -p arr
输出:
declare -a arr=([0]="1" [1]="2" [2]="3" [3]="4")
我认为第一个示例是函数式风格的 for 循环的翻译,那么这是怎么回事呢?
您的
parallel
似乎是 GNU 脚本,它是一个perl
并行运行命令的脚本。它非常努力地判断从哪个 shell 调用它,以便您传递给它的命令由该 shell 解释,但要做到这一点,它会在单独的进程中运行该 shell 的新调用。
如果你运行:
其中
strace
显示哪些命令由哪个进程执行,该xtrace
选项使 shell 显示它的作用。您将看到每个 bash shell 向其自己的 bash shell 附加一个元素
$arr
,然后退出,当然,它们自己的内存空间(包括其各自的$arr
数组)消失了,该$arr
数组不会bash
在系统上的所有 shell 调用之间自动共享。在任何情况下,同时运行命令意味着在不同的进程中运行它们,因此它无法在调用 shell 中运行这些函数,这些函数将在单独进程的新 shell 实例中运行,并且它们将更新这些 shell 的变量
arr
,不是您运行的 shell 之一parallel
。鉴于 bash 没有内置的多线程支持,即使是
parallel
shell 的内部命令或作为 shell 函数实现,它仍然需要在单独的进程中运行命令,每个进程都有自己的内存。您会在以下位置找到它:或者:
$arr
父 shell 的数组也没有被修改。如果您想收集并行启动的每个作业的结果,可以通过 stdout 或通过文件来完成。
例如:
(这里告诉我们
parallel
使用哪个 shell 以避免猜测)。请注意,
parallel
将每个 shell 的输出存储在临时文件中,并按顺序将它们转储到标准输出上,以便您以正确的顺序获取数组的元素。这有效:
该数组丢失了,因为它是在并行实例中设置的,与
echo
.