[Top][All Lists]

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

Re: Behaviour of test -v with assoc array and quote character in key

From: Daniel Gröber
Subject: Re: Behaviour of test -v with assoc array and quote character in key
Date: Mon, 15 Feb 2021 19:28:22 +0100
User-agent: NeoMutt/20180716

Hi Greg and Chet,

On Mon, Feb 15, 2021 at 08:48:15AM -0500, Greg Wooledge wrote:
> Do it this way instead:
> unicorn:~$ mytest() { array[$1]=123; test -v 'array[$1]'; echo "$?"; }

Ah! I didn't know test would exand that '$1' in there, cool.

> Yours expands $1 first, then passes array["] as an argument to test,
> which then performs a *second* round of expansion/parsing.

Right that's sort of what I figured I was seeing and I wasn't sure if this
is intentional.

> You might also want to look at the assoc_expand_once option, although
> single-quoting will work in a wider range of bash versions.

Thanks for the tip!

On Mon, Feb 15, 2021 at 09:11:48AM -0500, Chet Ramey wrote:
> `test' is always going to be problematic here because, as a shell builtin,
> its arguments undergo a round of word expansions before it's invoked. It's
> difficult to reliably detect the closing bracket in an array subscript as a
> result, even if the array subscript expansion didn't perform any expansions
> on its own. (Consider what would happen if $1 were `]').

You're absolutely right, I didn't consider the ']' case at all! That would
obviously break. So indeed this just user-error then and not really a bug.

> There are workarounds you can use to avoid the problem, involving adding a
> set of quotes to suppress the expansion the array subscript evaluation
> performs.

The `test -v 'array[$var]'` thing Greg suggested above seems pretty good to
me. Since the array subscript expands variables internally (which I didn't
know) that seems to be the way to go.

The workaround I came up with left to my own devices was to use eval
`printf %q`, I assume that's the sort of quoting you were referring to:

    # Usage: array_key_exists ARRAY KEY
    # The ARRAY argument must be a valid bash identifier, but this is not
    # checked. KEY may be any string.
    array_key_exists () {
            eval "[ -n \"\${$1[$(printf '%q' "$2")]:-}\" ]"

I was also wondering how array subscript interacts with `[[`, but it seems that

    [[ -v array[']'] ]]

has the same problem as `test`. Looking at the manual it says that while
word splitting and filename expansion isn't performed quote removal still
is so that's no help in this regard.

I wonder if this particular point, how to check an arbitrary array key
exists or not, is documented anywhere yet? I'd be happy to send a
patch. Can someone point me to the sections in the man{ual,page} that could
use commentary for this?


reply via email to

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