BASH关联数组打印

丹妮

有没有一种方法可以打印整个数组([key] = value)而不循环所有元素?

假设我创建了一个包含一些元素的数组:

declare -A array
array=([a1]=1 [a2]=2 ... [b1]=bbb ... [f500]=abcdef)

我可以用以下命令打印整个阵列

for i in "${!array[@]}"
do
echo "${i}=${array[$i]}"
done

但是,bash似乎已经知道如何一次“获取”所有数组元素-键${!array[@]}和值${array[@]}

有没有一种方法可以使bash在不循环的情况下打印此信息?

编辑:
typeset -p array做到了!
但是我不能在一次替换中同时删除前缀和后缀:

a="$(typeset -p array)"
b="${a##*(}"
c="${b%% )*}"

有没有更干净的方法来获取/打印输出的key = value部分?

伊尔卡楚

我想您在问两个不同的问题。

有没有一种方法可以使bash在不循环的情况下打印此信息?

是的,但是它们不如仅使用循环好。

有没有更干净的方法来获取/打印输出的key = value部分?

是的,for循环。它的优点是不需要外部程序,很简单,并且很容易控制确切的输出格式而不会出现意外。


任何尝试处理declare -ptypeset -p输出的解决方案都必须处理以下问题:a)变量本身包含括号或括号的可能性,b)declare -p必须添加引号以使其成为外壳程序的有效输入。

例如,b="${a##*(}"如果任何键/值包含左括号,则扩展将占用一些值。这是因为您使用了##,它删除了最长的前缀。相同c="${b%% )*}"尽管您当然可以declare更精确地匹配印刷的样板,但如果您不希望所有引用都做的话,您仍然会遇到困难。

除非您需要,否则它看起来不会很好。

$ declare -A array=([abc]="'foobar'" [def]='"foo bar"')
$ declare -p array
declare -A array='([def]="\"foo bar\"" [abc]="'\''foobar'\''" )'

使用for循环,可以更轻松地选择所需的输出格式:

# without quoting
$ for x in "${!array[@]}"; do printf "[%s]=%s\n" "$x" "${array[$x]}" ; done
[def]="foo bar"
[abc]='foobar'

# with quoting
$ for x in "${!array[@]}"; do printf "[%q]=%q\n" "$x" "${array[$x]}" ; done
[def]=\"foo\ bar\"
[abc]=\'foobar\'

从那里,以其他方式更改输出格式很简单(去掉键周围的括号,将所有键/值对放在一行上...)。如果您需要引用除Shell本身以外的内容,则仍然需要您自己报价,但至少您需要处理原始数据。(如果键或值中包含换行符,则可能需要使用一些引号。)

在当前的Bash(我认为是4.4)的情况下,您也可以使用printf "[%s]=%s" "${x@Q}" "${array[$x]@Q}"代替printf "%q=%q"它产生了一种更好的引用格式,但要记住要写的代码当然要花更多的功夫。(并且引用了@作为数组键的特殊情况,而%q没有引用。)

如果for循环似乎太疲倦而无法编写,请将其保存在某个函数中(此处不引用):

printarr() { declare -n __p="$1"; for k in "${!__p[@]}"; do printf "%s=%s\n" "$k" "${__p[$k]}" ; done ;  }  

然后使用:

$ declare -A a=([a]=123 [b]="foo bar" [c]="(blah)")
$ printarr a
a=123
b=foo bar
c=(blah)

也适用于索引数组:

$ b=(abba acdc)
$ printarr b
0=abba
1=acdc

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章