使用Bash 4.4,我使用“declare -n”编写了脚本,但今天我了解到,当我将这些脚本提供给RedHat 7用户时,脚本会因为BASH为4.2而失败。
这是一个小问题的例子,我想知道你是否可以建议我将这个方法反向移植到BASH 4.2:
#!/bin/bash
pwd=`pwd`
declare -A parms
parms[engine]=\"Sweave\"
parms[verbose]=FALSE
parms[tangle]=TRUE
## builds $parmstring by concatenating key=value pairs
catarr() {
declare -n __p="$1"
for k in "${!__p[@]}"
do parmstring+=", $k=${__p[$k]}"
done
}
parmstring=""
catarr parms
echo ${parmstring[*]}
输出应该是这样的:
$ bash bashmre.sh
, engine="Sweave", verbose=FALSE, tangle=TRUE
但在旧BASH上,RedHat表示声明不允许“-n”。
答案 0 :(得分:1)
我认为您可以使用eval
:
#!/bin/bash
pwd=`pwd`
declare -A parms
parms[engine]=\"Sweave\"
parms[verbose]=FALSE
parms[tangle]=TRUE
## builds $parmstring by concatenating key=value pairs
catarr() {
eval keys=(\"\${!$1[@]}\")
for k in "${keys[@]}"
do
eval val=\${$1[$k]}
parmstring+=", $k=$val"
done
}
parmstring=""
catarr parms
echo ${parmstring[*]}
我在bash 4.2.37上对此进行了测试并获得了所需的输出
答案 1 :(得分:0)
它根本不干净,但您可以生成然后执行代码。为了确保生成安全,请使用printf %q
替换值。
catarr() {
local eval_str
printf -v eval_str '
for k in "${!%q[@]}"; do
parmstring+=", $k=${%q[$k]}"
done
' "$1" "$1"
eval "$eval_str"
}
答案 2 :(得分:0)
我给@Charles Duffy和@shay的答案+1,但最后我没有使用任何一个答案。
我采取了查尔斯在我原来的帖子评论中提出的道路。我重写了这个东西,所以每个需要连接的数组都有一个单独的函数。在实际的应用程序中我们使用这个,有两个数组,“parms”和“myopts”,所以我最终得到了名为catparms和catmyopts的函数
catparms(){
for k in "${!parms[@]}"
do parmstring+=", $k=${parms[$k]}"
done
}
catmyopts(){
for k in "${!myopts[@]}"
do optstring+=", $k=${myopts[$k]}"
done
}
如果我有很多数组浮动,那么这种方法会变得乏味。
如果发生这种情况,我很确定我会回到依赖Bash 4.4的方法,并告诉那些老Bash的人他们必须升级或忘记它。我需要学习如何在脚本中添加代码来检测当前的Bash版本,如果不是4.3或更高版本则终止。我没有这样做,但可以。