如何动态地用数组项替换任意命令参数? [英] How can I dynamically substitute array entries for an arbitrary command parameter?
问题描述
此问题的灵感来自 for循环中的bash嵌套变量 .
如果我在bash中有一个数组,并且希望能够对该数组的每个元素运行一个任意命令,那么有没有一种方法可以通过通用函数(而不是循环)来做到这一点?那就是:
If I have an array in bash, and I want to be able to run an arbitrary command for every element of that array, is there a way to do that via a generic function, as opposed to with a loop? That is:
dest_array=( host1:/foo host2:/bar host3:/baz )
copy ./file dest_array
并将每个扩展名称为:
copy ./file host1:/foo
copy ./file host2:/bar
copy ./file host3:/baz
更好的是,有没有一种方法可以对多个数组执行此操作?例如:
Even better, is there a way to do this for multiple arrays? For instance:
sources=( first second )
dests=( host1:/foo host2:/bar )
copy sources dests
调用(不按特定顺序):
invoking (in no particular order):
copy first host1:/foo
copy first host2:/bar
copy second host1:/foo
copy second host2:/bar
推荐答案
考虑以下为bash 4.3或更高版本编写的函数:
Consider the following function, written for bash 4.3 or later:
run_for_each() {
local -n _items=$1; shift
local sigil=$1; shift
local -a args=( "$@" )
local -a call
local retval=0
for item in "${_items[@]}"; do
call=( "${args[@]//$sigil/$item}" )
"${call[@]}" || (( retval |= $? ))
done
return "$retval"
}
作为用法示例:
sources=( first second )
dests=( host1:/foo host2:/bar )
run_for_each sources SOURCE \
run_for_each dests DEST \
rsync -Pv SOURCE DEST
如果要使其并发,则可能看起来像这样:
If you wanted to make it concurrent, that might look like:
run_for_each_concurrent() {
local -n _items=$1; shift
local sigil=$1; shift
local -a args=( "$@" )
local -a pids=( )
local -a call
local retval=0
for item in "${_items[@]}"; do
call=( "${args[@]//$sigil/$item}" )
"${call[@]}" & pids+=( "$!" )
done
for pid in "${pids[@]}"; do
wait "$pid" || (( retval |= $? ))
done
return "$retval"
}
...它将在每个数组条目中同时运行一个进程;等待他们全部退出;并返回所有这些子流程的或"退出状态.
...which will run one process per array entry, all at the same time; wait for them all to exit; and return the ORed-together exit status of all those subprocesses.
顺便说一句-如果您没有bash 4.3,则可以通过替换以下行来使以上内容适用于较早的发行版:
By the way -- if you don't have bash 4.3, the above can be made to work with older releases by replacing this line:
local -n _items=$1; shift
显示以下内容:
printf -v cmd 'local -a _items=( "${%q[@]}" )' "$1" && eval "$cmd"; shift
这篇关于如何动态地用数组项替换任意命令参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!