并行处理:在zsh脚本中将输出追加到数组

时间:2018-07-26 17:42:33

标签: linux shell parallel-processing zsh

我有一个for循环,其中调用了函数task。每次对该函数的调用都会返回一个附加到数组的字符串。我想并行处理此for循环。我尝试使用&,但似乎不起作用。

这是未并行化的代码。

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

输出为:

hello 1 x
hello 2 x
hello 3 x

太好了!但是现在,当我尝试将其与

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

输出为空。

此问题专门针对zsh,与之对应的bash请参见here

2 个答案:

答案 0 :(得分:1)

我可能是错的,但是我很确定你不要想要做到这一点。

我将在下面保留原始解决方案,但请使用coproc进行尝试。

#! /usr/bin/zsh

coproc cat &

task(){
  sleep $1
  print -p "Sloppy simulation process # $1: $(date)"
}

arr=()

for i in {1..3}; do
    task $i &
done

for i in {1..3}; do
    read -p val
    arr+=("$val")
done

for i in "${arr[@]}"; do
    [[ -n "$i" ]] && echo "$i"
done

理想情况下,对coproc的写入将花费很长时间,以至于读取将首先开始并阻塞。

我想。

我的输出:

Sloppy simulation process # 1: Thu Jul 26 15:19:02 CDT 2018
Sloppy simulation process # 2: Thu Jul 26 15:19:03 CDT 2018
Sloppy simulation process # 3: Thu Jul 26 15:19:04 CDT 2018

  

原始文件存储版本


如果task是一个长期运行的步骤,那么可能值得并行处理工作,并增加将其存储在持久位置然后再加载数组的开销。这种快速破解有帮助吗?

task(){ # task() handles persistence itself
  sleep $1
  echo "Sloppy simulation process # $1: $(date)" >| /tmp/task/$1
}

mkdir -p /tmp/task/
cd /tmp/task 

for i in {1..3}
do  task $i & # run them in background
done
wait          # wait for the last one

arr=()
for f in *
do  arr[$f]="$(<$f)" # read each into arr
done

for i in $( seq ${#arr[@]} )
do [[ -n "${arr[$i]}" ]] && echo "${arr[$i]}" # show them
done

rm -fr /tmp/task/

答案 1 :(得分:1)

zsh随附zargs。为了对shell函数执行一些xargs式的并行操作,将很方便。

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

autoload -Uz zargs

arr=("${(@f)"$(zargs -P 3 -n 1 -- {3..1} -- task)"}")

print -l ${(qqq)arr}
#>> "hello 1"
#>> "hello 2"
#>> "hello 3"

这是zargs --help的输出:

Usage: zargs [options --] [input-args] [-- command [initial-args]]

If command and initial-args are omitted, "print -r --" is used.

Options:
--eof[=eof-str], -e[eof-str]
    Change the end-of-input-args string from "--" to eof-str.  If
    given as --eof=, an empty argument is the end; as --eof or -e,
    with no (or an empty) eof-str, all arguments are input-args.
--exit, -x
    Exit if the size (see --max-chars) is exceeded.
--help
    Print this summary and exit.
--interactive, -p
    Prompt before executing each command line.
--max-args=max-args, -n max-args
    Use at most max-args arguments per command line.
--max-chars=max-chars, -s max-chars
    Use at most max-chars characters per command line.
--max-lines[=max-lines], -l[max-lines]
    Use at most max-lines of the input-args per command line.
    This option is misnamed for xargs compatibility.
--max-procs=max-procs, -P max-procs
    Run up to max-procs command lines in the background at once.
--no-run-if-empty, -r
    Do nothing if there are no input arguments before the eof-str.
--null, -0
    Split each input-arg at null bytes, for xargs compatibility.
--replace[=replace-str], -i[replace-str]
    Substitute replace-str in the initial-args by each initial-arg.
    Implies --exit --max-lines=1.
--verbose, -t
    Print each command line to stderr before executing it.
--version
    Print the version number of zargs and exit.

在上面的示例中,它使用--max-procs=max-procs, -P max-procs--max-args=max-args, -n max-args