我想将多个命名数组原样传递给另一个bash脚本。 例如,给定 external.sh
echo "outer"
a=(1 2)
b=(3 4 5)
echo ${#a[@]}
echo ${#b[@]}
a=${a[@]} b=${b[@]} sh inner.sh
和inner.sh
echo "inner"
echo ${a[@]}
echo ${b[@]}
echo ${#a[@]}
echo ${#b[@]}
运行external.sh给出
$ sh outer.sh
outer
2
3
inner
1 2
3 4 5
1
1
也就是说,即使保留值,但它们的长度也会改变,这意味着它们不再是数组,而是字符串。
如何将多个命名数组原样传递给另一个bash脚本?
答案 0 :(得分:3)
有几种方法,每种方法都有其自身的缺点。
这意味着所有变量都是继承的,包括那些不能通过环境传递的变量(例如数组!)。
a=(1 2)
b=(3 4 5)
(. inner)
当然,这也意味着外壳程序设置(IFS
,set -e
等)也将被继承,因此inner.sh
需要被健壮地编写以处理可能发生的任何设置接收;并且以后不能用其他/非shell语言重写它。
eval
的代码(并信任您的呼叫者!)修改inner.sh
以运行[[ $setup ]] && eval "$setup"
,然后以以下方式调用它:
setup=$(declare -p a b) ./inner
很明显,如果您不控制流程环境,这将带来严重的安全风险。
在这里,我们传递每个数组的名称,长度和原始元素。
inner
需要修改,以将命令参数列表中的项目复制回数组,如以下示例所示:
while (( $# )); do # iterating over our argument list:
dest_name=$1; shift # expect the variable name first
dest_size=$1; shift # then its size
declare -g -a "$dest_name=( )" # initialize our received variable as empty
declare -n dest="$dest_name" # bash 4.3: make "dest" point to our target name
while (( dest_size )) && (( $# )); do # and then, for up to "size" arguments...
dest+=( "$1" ); shift # pop an argument off the list onto an array
(( dest_size -= 1 )) # and decrease the count left in "size"
done
unset -n dest # end that redirection created above
done
...,然后以outer
扩展为该格式:
./inner a "${#a[@]}" "${a[@]}" b "${#b[@]}" "${b[@]}"