gpt4 book ai didi

Bash:如何使用包含方括号或其他特殊字符的键来保留和恢复关联数组

转载 作者:行者123 更新时间:2023-11-29 09:04:29 25 4
gpt4 key购买 nike

问题

获取 declare -p 的结果对于键包含方括号的有效 Bash 关联数组,会导致错误的数组下标错误。

测试程序

做:

$ 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 (Core) 服务器上

解决方法

如果不是做 declare -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 文件就可以了。请注意,在上面的示例中,我还转义了可能是 key 一部分的引号字符。我确实明白我上面的内容并不详尽。由于这些复杂性,如果可能的话,我更喜欢不涉及此类变通办法的解决方案。

问题

有没有shopt , set -o <option> ,或者我可以做些什么来使我能够将其键可能包含方括号或其他特殊字符的关联数组持久保存到文件中,并在以后能够成功地获取该文件?我需要一个适用于上述环境的解决方案。

最佳答案

这是一个错误

这是 bash 4.2 中的错误。它已在 4.3 中修复。

我通过编译来自 http://ftp.gnu.org/gnu/bash/bash 4.24.2.534.3 测试了这个并重复上述步骤。 4.3 的行为类似于 4.4 - 没有这样的问题。然而,在 bash 4.3 中,declare 将打印

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 个字符串而不是一个(当然是引用)时,才会发生这种情况。该设置允许轻松完成此操作,因此我将其添加到此处。

这可以让您解决使用预定义函数难以与现有代码交互的情况。

关于Bash:如何使用包含方括号或其他特殊字符的键来保留和恢复关联数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45665194/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com