bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Changing the way bash expands associative array subscripts


From: Lawrence Velázquez
Subject: Re: Changing the way bash expands associative array subscripts
Date: Tue, 16 Mar 2021 02:02:45 -0400

> On Mar 15, 2021, at 9:03 PM, Léa Gris <lea.gris@noiraude.net> wrote:
> 
> Please excuse my profanity of mentioning zsh in this list, but I really think 
> features and behavior convergence can benefit end users in multiple ways, 
> especially when expanding beyond the POSIX sh scope.
> 
> What direction has taken zsh with expanding associative array indexes?

Broadly speaking, zsh treats subscript expressions as if they are 
double-quoted, but it does not perform arithmetic expansion on associative 
array indices (although subscript expressions must still adhere to related 
parsing rules).

        % zsh --version; echo
        zsh 5.8 (x86_64-apple-darwin18.7.0)

        % cat /tmp/demo1
        # Chet's example modified to highlight certain behaviors
        foo() {
            echo uname >&2
            echo +1
        }

        declare -A assoc
        key='x$(foo)]=1,b[1$(foo)'

        assoc[$key]=0
        declare -p assoc b

        % zsh -f /tmp/demo1
        /tmp/demo1:declare:10: no such variable: b
        typeset -A assoc=( ['x$(foo)]=1,b[1$(foo)']=0 )

However, it does perform multiple expansions in arithmetic contexts.

        % cat /tmp/demo2
        # Chet's example modified to highlight certain behaviors
        foo() {
            echo uname >&2
            echo +1
        }

        declare -A assoc
        key='x$(foo)]=1,b[1$(foo)'

        (( assoc[$key]++ ))
        declare -p assoc b

        % zsh -f /tmp/demo2
        uname
        uname
        typeset -A assoc=( [x+1]=1 )
        typeset -a b=( '' 1 )

Furthermore, "as if they are double-quoted" is rather literal. (Special 
handling allows the use of a["foo"] instead of a[\"foo\"].)

        % cat /tmp/demo3
        declare -A a
        key='$(echo foo)'
        a[$key]=1
        a['$key']=2
        a["foo"]=3

        declare -p a

        % zsh -f /tmp/demo3
        typeset -A a=( ['"foo"']=3 ['$(echo foo)']=1 [\''$(echo foo)'\']=2 )

If we tweak the preamble to create the intended array (and disable NOMATCH to 
treat failed filename generation as bash does), the unset commands work the 
same as in Chet's proposal.

        % cat /tmp/demo4
        declare -A a
        key='$(echo foo)'
        a[$key]=1
        a[\$key]=2
        a[foo]=3

        # Avoid Chet's intentional error because it's difficult to get zsh to
        # imitate it faithfully.
        #unset -v a[$key]
        declare -p a

        # unsets element with key $key
        unset -v a['$key']
        declare -p a

        # unsets element with key $(echo foo)
        unset -v a["$key"]
        declare -p a

        # unsets element with key foo
        eval unset -v a\["$key"\]
        declare -p a

        % zsh -f +o NOMATCH /tmp/demo4
        typeset -A a=( ['$(echo foo)']=1 ['$key']=2 [foo]=3 )
        typeset -A a=( ['$(echo foo)']=1 [foo]=3 )
        typeset -A a=( [foo]=3 )
        typeset -A a=( )

vq


reply via email to

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