[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Help-bash] Expansions in associative array subscripts
From: |
Greg Wooledge |
Subject: |
Re: [Help-bash] Expansions in associative array subscripts |
Date: |
Wed, 7 Aug 2019 08:49:16 -0400 |
User-agent: |
Mutt/1.10.1 (2018-07-13) |
On Wed, Aug 07, 2019 at 11:07:47AM +1000, David wrote:
> Below I ask a specific question, but for general context I am uncertain
> about things like:
>
> "${associativeArray[key]}"
Here, the three-character string key is the key.
> "${associativeArray[$key]}"
Here, the content of the variable named key is the key, with the
additional restriction that it'll blow up if the variable is empty.
$ declare -A aa
$ key=
$ aa[$key]=foo
bash: aa[$key]: bad array subscript
Empty keys are not allowed.
> "${associativeArray[?]}"
The one-character string ? is the key. No globbing is done.
> "${associativeArray[*]}"
The one-character string * is the key. No globbing is done.
> because I am unclear whether I should also use additional quoting inside
> the [subscript], and if so then how.
Well, generally speaking it shouldn't hurt. aa["$key"]=value and
aa[$key]=value should both be fine. On the expansion side, both
"${aa["$key"]}" and "${aa[$key]}" should be fine.
> So the general questions are:
> What are the dangers from unexpected expansions?
There shouldn't be any "unexpected expansions".
> Does the subscript need to be quoted?
Only if it's a literal string that needs quoting due to metacharacters
inside it. E.g. aa["my]key"] needs quotes because of the ] character.
> Does it need to be quoted separately from any outer context?
If applicable, yes. "${aa["my]key"]}"
> But, we are generally advised to QEFE, so shouldn't that be
> associativeArray["$key"] ?
If you like.
> But how could we nest those quotes inside, while simultaneously quoting
> the outer array expansion
> "${associativeArray[$key]}" ?
As I showed earlier. Exactly the same as "${foo/bar/"$baz"}" or
"$(cmd1 "$arg1")" where quotes nest because of syntax in between the
sets of quotes.
> Or do the outer quotes there do both jobs?
No, they don't.
> Which then leads me to my specific question...
>
> This sentence from 'man bash' (it appears under the heading 'Arrays', in
> the paragraph about 'unset') makes me very uncomfortable ...
>
> "Care must be taken to avoid unwanted side effects caused by pathname
> expansion."
>
> I cannot understand the scope of that sentence, or its relationship to the
> sentences that surround it.
That sentence doesn't appear in the 5.0 man page. It appears in the 4.4
man page, though.
Bash 4.4:
The unset builtin is used to destroy arrays. unset name[subscript]
destroys the array element at index subscript. Negative subscripts to
indexed arrays are interpreted as described above. Care must be taken
to avoid unwanted side effects caused by pathname expansion. unset
name, where name is an array, or unset name[subscript], where subscript
is * or @, removes the entire array.
Bash 5.0:
The unset builtin is used to destroy arrays. unset name[subscript] de‐
stroys the array element at index subscript, for both indexed and asso‐
ciative arrays. Negative subscripts to indexed arrays are interpreted
as described above. Unsetting the last element of an array variable
does not unset the variable. unset name, where name is an array, or
unset name[subscript], where subscript is * or @, removes the entire
array.
The warning is about cases like this:
$ touch a1
$ a=(zero one two)
$ unset a[1]
$ declare -p a
declare -a a=([0]="zero" [1]="one" [2]="two")
In that example, a[1] is globbed to a1 because of the file named a1 in
the current working directory. So the resulting command is unset a1,
which is very different from unset 'a[1]'.
$ unset 'a[1]'
$ declare -p a
declare -a a=([0]="zero" [2]="two")