如何动态地用数组项替换任意命令参数? [英] How can I dynamically substitute array entries for an arbitrary command parameter?

查看:51
本文介绍了如何动态地用数组项替换任意命令参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题的灵感来自 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆