问题
I can create an associative array and assign an integer to a key that contains a single quote in it:
$ declare -A dict
$ var="john's"
$ dict[$var]=1
$ echo ${dict[$var]}
1
$ declare -p dict
declare -A dict=(["john's"]="1" )
But when I try to increment its value:
$ (( dict[$var]++ ))
bash: ((: dict[john's]++ : bad array subscript (error token is "dict[john's]++ ")
$ (( dict["$var"]++ ))
bash: ((: dict[john's]++ : bad array subscript (error token is "dict[john's]++ ")
$ (( dict["${var}"]++ ))
bash: ((: dict[john's]++ : bad array subscript (error token is "dict[john's]++ ")
I always get the same error. What am I doing wrong?
回答1:
The single quote in key
name is causing the parser to treat it as a un-terminated quote character. One way to fix this would be to escape the '
character in the key
key="john's"
printf -v escKey "%q" "$key"
now because of the %q
specifier, printf() would have applied required escapes to all shell meta characters i.e. making it "shell-quoted" and re-usable. If you print the contents of escKey
you'll notice the '
escaped
printf '%s\n' "$escKey"
john\'s
Now you can use this keyname in your associative array. Remember you can always manually add the escapes which could be messy. Since %q
is a native way provided by the shell, it is much safe to use it.
(( dict["$escKey"]++ ))
Also in bash
versions >= 4.4 parameter expansion has @Q
which is a shortcut for %q
specifier of printf()
using which you can do
(( dict["${key@Q}"]++ ))
回答2:
Turn off multiple evaluation* of associative array subscripts with following command and it'll work.
shopt -s assoc_expand_once
* An example showing the default behavior and assoc_expand_once
's effect:
$ v1=42 $ v2='$v1' $ declare -A foo $ foo[$v2]= $ declare -p foo declare -A foo=(
["\$v1"]="") $ (( foo[$v2]++ )) $ declare -p foo declare -A foo=(
[42]="1" ["\$v1"]="") $ $ shopt -s assoc_expand_once $ (( foo[$v2]++ )) $ declare -p foo declare -A foo=(
[42]="1" ["\$v1"]="1")
来源:https://stackoverflow.com/questions/61701799/bad-array-subscript-error-when-trying-to-increment-an-associative-array-element