help-bash
[Top][All Lists]
Advanced

[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")



reply via email to

[Prev in Thread] Current Thread [Next in Thread]