为有效的Bash关联数组获取declare -p的结果,其中键包含方括号会导致错误的数组下标错误.
测试程序
做:
$declare -A array $key='var[0]' $array["$key"]=37 $echo ${array["$key"]} 37 $declare -p array > def.sh $cat def.sh declare -A array='(["var[0]"]="37" )' $. def.sh bash: [var[0]]=37: bad array subscript
在上面的代码中,请注意:
>我能够指定包含方括号的键:var [0]
>该密钥引用了setter和getter
>我可以使用此密钥进行分配
>我可以使用此键从关联数组中获取值
>使用declare -p我可以将此定义保存到文件:def.sh
>在获取文件def.sh时会发出错误.
我的环境
>我正在使用的Bash版本是4.2.46(1)-release(x86_64-redhat-linux-gnu).
>我在CentOS 7.3.1611(核心)服务器上
如果不是做声明-p array>我改为def.sh:
{ echo 'declare -A array' for Key in "${!array[@]}"; do EscapedKey="$(sed 's|"|\\"|g' <<<"$Key")" echo "array[\"$EscapedKey\"]=${array["$Key"]}" done } > def.sh
然后采购def.sh文件.请注意,在上面的示例中,我还要转义可能是键的一部分的引号字符.我明白我上面所说的并不详尽.由于这些复杂性,如果可能的话,我宁愿选择不涉及此类变通方法的解决方案.
题
是否有一些shopt,set -o< option>或其他我可以做的事情让我能够持久保存一个关联数组,其关键字可能包含方括号或其他特殊字符到文件中,以后能够成功获取该文件?我需要一个在我的环境中工作的解决方案.
解决方法
我通过从http://ftp.gnu.org/gnu/bash/编译bash 4.2,4.2.53和4.3来测试这个并复制了上面的步骤. 4.3表现得像4.4 – 没有这样的问题.然而,在bash 4.3中,声明将打印
declare -A array='(["var[0]"]="37" )'
就像4.2一样. 4.4不会在右侧添加引号,而是打印此:
declare -A array=(["var[0]"]="37" )
这与测试显示的结果没有区别.
在complete_fullquote中有一个可能相关的选项,但它在4.4中添加,因此它不能用作解决方法.
似乎除了使用版本> = 4.3之外,这需要解决,而您使用的版本是最简单的方法.
如果你想避免使用sed调用(使用bash 4.2测试),还有另一种方法:
function array2file { # local variable for the keys declare -a keys # check if the array exists,to protect against injection # by passing a crafted string declare -p "$1" >/dev/null || return 1; printf "declare -A %s\n" "$1" # create a string with all the keys so we can iterate # because we can't use eval at for's declaration # we do it this way to allow for spaces in the keys,since that's valid eval "keys=(\"\${!$1[@]}\")" for k in "${keys[@]}" do printf "%s[\"${k//\"/\\\\\"}\"]=" "$1" # the extra quoting here protects against spaces # within the element's value - injection doesn't work here # but we still need to make sure there's consistency eval "printf \"\\\"%s\\\"\n\" \"\${$1[\"${k//\"/\\\"}\"]}\"" done }
这将在键周围正确添加引号,并且还可以在键本身内转义所有双引号.您可以将其放在您提供的文件中.然后使用:
array2file array > ./def.sh
其中array是您选择的任何数组名称.通过重定向输出,您将获得正确引用的键,您可以像以前一样定义关联数组,然后将其传递给此函数进行存储.
额外的功劳
如果将for循环中第一个printf提供的变量从$1更改为${2: – $1}并在顶部的printf处执行相同操作,则可以选择使用第二个参数创建新数组的定义正如其名称,允许重命名.只有当您提供2个字符串而不是1个字符串时才会发生这种情况(当然引用).设置允许轻松完成,所以我在这里添加了它.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。