Bash 如果提前声明数组,数组赋值失败

Bash array assignment fails if you declare the array in advance

这个有效:

$ BAR=(a b c)
$ echo "${BAR[1]}"
b

然而,这不是:

$ declare -A FOO
$ FOO=(a b c)
bash: FOO: a: must use subscript when assigning associative array
bash: FOO: b: must use subscript when assigning associative array
bash: FOO: c: must use subscript when assigning associative array

文档声称下标是可选的:

Arrays are assigned to using compound assignments of the form name=(value1 ... valuen), where each value is of the form [subscript]=string. Only string is required.

使用declare 会改变这里数组赋值的语法吗?为什么用 declare 提示 bash 变量类型会改变事情? (为什么 declare 根本存在——如果我将一个数组赋给一个变量,那么这个变量就是一个数组……不是吗?)

$ declare -A FOO

这是在声明关联数组。注意大小写的区别,-a 用于声明一个(索引)数组。

$ declare -a FOO

declare -a 声明一个由整数索引的数组。

declare -A 声明一个由字符串索引的关联数组。

你必须使用:

FOO=([1]="a" [2 or 3]="b or c")

或类似的符号分配给关联数组,并且:

echo "${FOO[2 or 3]}"

访问它们。

您不能像那样初始化用 -A 声明的基于简单索引的数组。

使用这个:

declare -A foo
foo=( [x]="A" [y]="B" [z]="C" )

或者只是:

declare -A foo=( [x]="A" [y]="B" [z]="C" )

要在关联数组中使用基于索引的索引,请使用:

declare -A foo=( [0]="a" [1]="b" [2]="c" )

您使用了 -A 选项来创建关联数组变量 相反,您应该尝试使用选项 -a.

创建数组变量

bash-3.2$ declare -a BOO

bash-3.2$ BOO=(a b c)

bash-3.2$

bash-3.2$ echo "${BOO[1]}"

b

bash-3.2$ echo "${BOO[2]}"

c

bash-3.2$

根据其他答案,这是 Bash 中关联(键=值对)和索引(索引 0-无穷大,值)数组之间的区别。

现在,如果您想通过构建索引数组并将其转换为关联数组来做一个聪明的技巧,这是可能的,但请记住转换为 [=19= 的 "values" ] 在数组中必须是唯一的,否则它们将被覆盖,除非您跟踪给定 "value" 被看到的次数并将索引插入到每个 "key".[=12 的值数组中=]

https://unix.stackexchange.com/a/177589

declare -a array1
array1=() # Empty the array to avoid repeated runs introducing side effects

# Using `+=($stuff)` adds to an array, using `+=$stuff` concatenates text
# if $stuff might have spaces, double quote it! or just always quote!
# see the tricky 'bar baz' with a space
for eachword in foo 'bar baz' fizzbuzz; do array1+=("$eachword"); done

# Make SURE you quote the array when looping over in case values have spaces
for eachword in "${array1[@]}"; do echo "$eachword"; done

declare -A map    # required: declare explicit associative array

for key in "${!array1[@]}"     # expand the array indexes to a list of words
do
  # Check uniqueness note
  map[${array1[$key]}]="$key"  # exchange the value ${array1[$key]} with the index $key
done

# Debug printing the new associative array
for eachkey in "${!map[@]}"; do echo "${eachkey}"; done
for eachvalue in "${map[@]}"; do echo "${eachvalue}"; done

a=fizzbuzz
[[ -n "${map[$a]}" ]] && printf '%s is in array\n' "$a"

# UNIQUENESS NOTE
# Add code before the map if you won't have unique "keys"
# It should check if the $array1[$key] already exists and make its "value"  an array where you append every new index where it existed
# NOTE: there may be some limitations with nested arrays in Bash

小心,在我的例子中,我收到此错误是因为在 = 之前和之后我添加了 space.

declare -A table_queries=(
    ["cluster"] = "select * from cluster where report_version_id = $REPORT_VERSION_ID"
) # Incorrect

declare -A table_queries=(
    ["cluster"]="select * from cluster where report_version_id = $REPORT_VERSION_ID"
) # Correct