如何使用命令输出填充 bash 关联数组?

Ed *_*ton 8 bash

我试图用命令的输出填充关联数组。我可以在没有命令的情况下做到这一点:

$ declare -A x=( [first]=foo [second]=bar )
$ echo "${x[first]}, ${x[second]}"
foo, bar
Run Code Online (Sandbox Code Playgroud)

我可以用命令输出填充一个非关联数组:

$ declare y=( $(echo 'foo bar') )
$ echo "${y[0]}, ${y[1]}"
foo, bar
Run Code Online (Sandbox Code Playgroud)

但是当我尝试在上述两个基础上构建一个语句来从命令填充关联数组时,我收到以下错误消息:

$ declare -A z=( $(echo '[first]=foo [second]=bar') )
-bash: z: $(echo '[first]=foo [second]=bar'): must use subscript when assigning associative array
Run Code Online (Sandbox Code Playgroud)

为什么我会收到该错误消息以及使用命令输出填充关联数组的正确语法是什么?我试图避免使用eval用于通常的原因,不想使用临时文件,当然echo只是被用作产生问题的效果的命令的例子,真正的命令将更加复杂。

因此,根据以下几个答案,看起来只是我的引用有问题:

$ declare -A z="( $(echo '[first]=foo [second]=bar') )"
$ echo "${z[first]}, ${z[second]}"
foo, bar
Run Code Online (Sandbox Code Playgroud)

并在索引和值中有空格:

$ declare -A z="( $(echo '[first field]="foo with space" [second]="space bar"') )"
$ echo "${z[first field]}, ${z[second]}"
foo with space, space bar
Run Code Online (Sandbox Code Playgroud)

编辑以回应评论中关于为什么需要引号的问题(如何使用命令输出填充 bash 关联数组?)-我不完全知道,但也许其他人可以使用此脚本的结果作为参考进行解释(不期望在索引数组中使用指定的索引,它们只是作为数组值填充的字符串的一部分):

$ cat tst.sh
#!/bin/env bash

set -x

printf 'Indexed, no quotes\n'
declare -a w=( $(echo '[first]=foo [second]=bar') )
declare -p w

printf '\n---\n'

printf 'Indexed, with quotes\n'
declare -a x="( $(echo '[first]=foo [second]=bar') )"
declare -p x

printf '\n---\n'

printf 'Associative, no quotes\n'
declare -A y="( $(echo '[first]=foo [second]=bar') )"
declare -p y

printf '\n---\n'

printf 'Associative, with quotes\n'
declare -A z=( $(echo '[first]=foo [second]=bar') )
declare -p z
Run Code Online (Sandbox Code Playgroud)

.

$ ./tst.sh
+ printf 'Indexed, no quotes\n'
Indexed, no quotes
+ w=($(echo '[first]=foo [second]=bar'))
++ echo '[first]=foo [second]=bar'
+ declare -a w
+ declare -p w
declare -a w=([0]="[first]=foo" [1]="[second]=bar")
+ printf '\n---\n'

---
+ printf 'Indexed, with quotes\n'
Indexed, with quotes
++ echo '[first]=foo [second]=bar'
+ declare -a 'x=( [first]=foo [second]=bar )'
+ declare -p x
declare -a x=([0]="bar")
+ printf '\n---\n'

---
+ printf 'Associative, no quotes\n'
Associative, no quotes
++ echo '[first]=foo [second]=bar'
+ declare -A 'y=( [first]=foo [second]=bar )'
+ declare -p y
declare -A y=([second]="bar" [first]="foo" )
+ printf '\n---\n'

---
+ printf 'Associative, with quotes\n'
Associative, with quotes
+ z=($(echo '[first]=foo [second]=bar'))
./tst.sh: line 24: z: $(echo '[first]=foo [second]=bar'): must use subscript when assigning associative array
+ declare -A z
+ declare -p z
declare -A z=()
Run Code Online (Sandbox Code Playgroud)

anu*_*ava 7

这是从命令的输出填充关联数组的传统 while 循环方法:

while IFS= read -r; do
   declare -A z+="( $REPLY )"
done < <(printf '[first]=foo [second]=bar\n[third]=baz\n')

# check output
$> echo "${z[first]}, ${z[second]}, ${z[third]}"
foo, bar, baz

# or declare -p
$> declare -p z
declare -A z='([third]="baz" [second]="bar" [first]="foo" )'
Run Code Online (Sandbox Code Playgroud)

编辑:您最初的尝试也适用于正确的报价:

$> unset z

$> declare -A z="( $(echo '[first]=foo [second]=bar') )"

$> declare -p z
declare -A z='([second]="bar" [first]="foo" )'
Run Code Online (Sandbox Code Playgroud)