简体   繁体   English

并行过程:在bash脚本中将输出追加到数组

[英]Parallel processes: appending outputs to an array in a bash script

I have a for loop in which a function task is called. 我有一个for循环,其中调用了一个功能task Each call to the function returns a string that is appended to an array. 每次对该函数的调用都会返回一个附加到数组的字符串。 I would like to parallelise this for loop. 我想并行处理此for循环。 I tried using & but it does not seem to work. 我尝试使用&但似乎无法正常工作。

Here is the code not parallelised. 这是未并行化的代码。

task (){ sleep 1;echo "hello $1"; }
arr=()

for i in {1..3}; do
    arr+=("$(task $i)")
done

for i in "${arr[@]}"; do
    echo "$i x";
done

The output is: 输出为:

hello 1 x
hello 2 x
hello 3 x

Great! 大! But now, when I try to parallelise it with 但是现在,当我尝试将其与

[...]
for i in {1..3}; do
    arr+=("$(task $i)")&
done
wait
[...]

the output is empty. 输出为空。

GNU Parallel is good at doing stuff in parallel :-) GNU Parallel擅长并行处理:-)

task (){ sleep 1;echo "hello $1"; }

# Make "task" known to sub shells
export -f task

# Do tasks in parallel
parallel -k task ::: {1..3}

Sample Output 样本输出

hello 1
hello 2
hello 3

I am suggesting you do - but Charles kindly points out that this is a known bash pitfall: 我建议您这样做-但是Charles指出这是一个众所周知的bash陷阱:

array=( $(parallel -k task ::: {1..3}) )

Charles' suggested solution is: 查尔斯建议的解决方案是:

IFS=$'\n' read -r -d '' -a array < <(parallel -k task ::: 1 2 3 && printf '\0')

Try encapsulating your adding step into a function or a temporary script, but send the items to a file instead. 尝试将添加步骤封装到函数或临时脚本中,但是将项目发送到文件中。 I think you will need some command that I can't remember on top of my head for dealing with file lock. 我认为您将需要一些我不记得的命令来处理文件锁定。 See if you need to export things too. 看看您是否也需要导出内容。 Then you source the file at the end. 然后,在最后获取文件。 Something like: 就像是:

echo 'arr=(' > temp
add() { echo item >> temp; }
...
export -f add
...
add &
...
echo ')' > temp
source temp
rm temp

You are looking for parset (part of GNU Parallel since 20170422) or env_parset (available since 20171222): 您正在寻找parset (自20170422起为GNU Parallel的一部分)或env_parset (自20171222起可用):

# If you have not run:
#    env_parallel --install
# and logged in again, then you can instead run this to activate (env_)parset:
. `which env_parallel.bash`

task (){
  echo "hello $1"
  sleep 1.$1
  perl -e 'print "binary\001\002\n"'
  sleep 1.$1
  echo output of parallel jobs do not mix
}
env_parset arr task ::: {1..3}
env_parset a,b,c task ::: {1..3}

echo "${arr[1]}" | xxd
echo "$b" | xxd

parset is supported in Bash/Ksh/Zsh (including arrays), ash/dash (without arrays). Bash / Ksh / Zsh(包括数组),ash / dash( parset )支持parset

Try encapsulating your adding step into a function or a temporary script. 尝试将添加步骤封装到函数或临时脚本中。 See if you need to export things too. 看看您是否也需要导出内容。 Something like: 就像是:

add() { arr+=(value); }
...
export -f add
...
add &

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM