将命名数组传递到另一个bash脚本

时间:2018-11-29 02:45:31

标签: arrays bash shell

我想将多个命名数组原样传递给另一个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脚本?

1 个答案:

答案 0 :(得分:3)

有几种方法,每种方法都有其自身的缺点。


简单方法:在Subshel​​l中运行内部脚本

这意味着所有变量都是继承的,包括那些不能通过环境传递的变量(例如数组!)。

a=(1 2)
b=(3 4 5)
(. inner)

当然,这也意味着外壳程序设置(IFSset -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[@]}"