多个(带有一个固定的)GNU 并行参数



我使用 GNU-parallel 来重复调用函数foo。该函数有两个参数,一个文件名(在下面的示例中a,保存在数组A中)和一个过滤器数组(B下面,b作为B的元素)。

该函数应该遍历AB的所有组合,但是,问题是,我实际上只使用并行来迭代A,同时为每个函数调用提供B

作为最小示例:

#!/bin/bash
A=("1" "2" )
B=("X" "Y")
foo() {
a=$1 # a single element of A
B=$2 # the whole array B
for b in "${B[@]}"; do
printf "a = %s; b = %sn" $a $b
done
echo "-----------------"
}
export -f foo
# goal:
echo "Sequential (aka, the target) ==="
for a in "${A[@]}"; do
foo $a $B
done

结果

Sequential (aka, the target) ===
a = 1; b = X
a = 1; b = Y
-----------------
a = 2; b = X
a = 2; b = Y
-----------------

请注意,我们没有对每个组合进行一次调用,而是只对A每个组合进行一次调用,然后在函数中迭代B

并行尝试:

尝试 1

parallel foo ::: "${A[@]}" ::: "${B}"

结果在

a = 1; b = X
-----------------
a = 2; b = X
-----------------

(缺少B的第二个参数)

尝试 2

parallel foo ::: "${A[@]}" ::: "${B[@]}" 

结果在

a = 1; b = X
-----------------
a = 1; b = Y
-----------------
a = 2; b = X
-----------------
a = 2; b = Y
-----------------

(每个组合一个调用,而不是每个 A 一个调用,然后迭代 B)

我已经浏览了手册和SO,但找不到解决方案。

编辑

我觉得当我直接导出数组 B 时它应该可以工作,但也没有得到任何结果

foo2() {
a=$1 # a single element of A
# B=$2 # the whole array B
for b in "${B[@]}"; do
printf "a = %s; b = %sn" $a $b
done
echo "-----------------"
}
export -f foo2
export B
parallel foo ::: "${A[@]}"

结果在

-----------------
-----------------

(显然是空的B)

你的问题源于B是一个数组。我以前从未见过数组作为参数传递给函数,我不确定它是否可以完成。

第二个问题是,虽然您可以导出函数和变量,但您无法在不作弊的情况下导出数组: 在 bash 脚本中导出数组

GNU 并行使得通过使用env_parallel来作弊变得容易。这会将完整环境导出到运行命令的 shell:数组、变量、别名和函数。它甚至可以在远程运行命令时这样做。

env_parallel在过去一年中改进了很多,因此如果您拥有的版本导致问题,请升级。

#!/bin/bash                                                                        
A=("1" "2" )
B=("X" "Y")
foo() {
a=$1 # a single element of A                                                   
#    B=$2 # the whole array B                                                      
for b in "${B[@]}"; do
printf "a = %s; b = %sn" $a $b
done
echo "-----------------"
}
# If you have earlier run 'env_parallel --install'                                 
# to activate env_parallel in your shell                                           
# this should work.                                                                
env_parallel foo ::: "${A[@]}"
# If you have not, then this should work:
. `which env_parallel.bash`
env_parallel foo ::: "${A[@]}"

最新更新