arrays - 将命名数组传递给另一个 bash 脚本
问题描述
我想将多个命名数组按原样传递给另一个 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 脚本?
解决方案
有几种方法可用,每种方法都有自己的缺点。
简单的方法:在子shell中运行内部脚本
这意味着所有变量都是继承的,包括那些不能通过环境传递的变量(比如数组!)。
a=(1 2)
b=(3 4 5)
(. inner)
当然,这也意味着 shell 设置(IFS
,set -e
等)也是继承的,因此inner.sh
需要健壮地编写以处理它可能碰巧接收到的任何设置;并且您以后不能用其他/非shell语言重写它。
不安全的方式:通过eval
-able 代码(并相信你的调用者!)
修改inner.sh
为 run [[ $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[@]}"
推荐阅读
- r - 如何在R中对不同数据帧的同一列求和
- linux-kernel - 内核 4.18.10:缺少驱动程序 e100 的固件 d102e_ucode.bin
- node.js - 为什么 bootstrap-vue 需要我手动安装 jquery 和 webpack,即使我已经全局安装了它们?
- python - 如何获取 TCP 包的包数?
- python - 在 Python GTK 中从 ListBox(绑定到 ListStore)中获取选定对象
- jquery - 如何在 Kendo Grid 列中显示复选框
- winapi - FP-precision related "Debug Assertion Failed!" (I have no idea why this is happening)
- android - 无法安装 Apk 更新版本
- python - discord.py 上是否有用于用户名更改的事件处理程序?
- django - How to prevent default image from being deleted when a user gets deleted?