[Toybox] bash continues to confuse me.

Chet Ramey chet.ramey at case.edu
Thu Jun 18 11:46:20 PDT 2020

On 6/17/20 1:22 PM, Rob Landley wrote:
> Trying to figure out when spaces are and aren't allowed in ${blah} led to asking
> why echo ${!a* } is an error but ${!a@ } isn't (when there are no variables
> starting with a), and I eventually worked out that:
>   $ X=PWD
>   $ echo ${!X at Q}
>   '/home/landley/toybox/clean'
> Is going on? 

It's variable transformation. It's introduced by `@' and uses single-letter
operators. I cribbed the idea from mksh and extended it. The syntax is kind
of loose because I'm still experimenting with it.

Which is just weird, both because:
>   $ echo ${PATH@ }
>   bash: ${PATH@ }: bad substitution
> And because:
>   $ ABC=defghi; echo ${#ABC at Q}
>   bash: ${#ABC at Q}: bad substitution

The #variable is the entire expansion, not the `parameter' part of an

>   $ echo ${PWD:1:3 at Q}
>   bash: PWD: 3 at Q: value too great for base (error token is "3 at Q")
>   $ echo ${PWD:1 at Q}
>   bash: PWD: 1 at Q: value too great for base (error token is "1 at Q")

What's wrong with that? `@' and `Q' are valid characters in numeric
constants when the base is large enough to need them. You can use
bases up to 64 in base#constant.
> Hmmm...
>   $ echo ${!potato at walrus}
>   $ echo ${!P at walrus}

Invalid transformations just expand to nothing rather than being errors.
That's part of what I'm still experimenting with.

>   $ echo ${!P@}

Yep, variable transformation isn't in effect when the expansion ends with
the `@'.

>   $ X=PATH
>   $ echo ${!X@ }
>   bash: ${!X@ }: bad substitution
>   $ ABC=123
>   $ echo ${!A at walrus}
>   $ echo ${!ABC@}
>   ABC
>   $ echo ${!ABC at walrus}
>   $ echo ${!A@ }
> Ok, when X exists and points to another variable, then !X becomes the contents
> of that other variable and THEN the @ cares about trailing garbage. But * is a
> different codepath from @...?

It's a different expansion.

> And when the ${!var} doesn't have contents pointing to another existing
> variable, it falls back to a codepath that tries the prefix stuff (and/or the
> array stuff, in some order?) and that codepath tries to parse trailing @Q and
> friends, but DOESN'T error out if it can't recognize the trailing stuff after the @?

Not really, no. It grabs the parameter, which may begin with `!', looks at
the character following it, does one character of lookahead if that
character is `@', and branches to the appropriate thing: variable prefix
expansion or indirect expansion with the result being used as the parameter
for the rest of the expansion.

> I'm pretty sure the array mangling logic ties in here somehow, but there's some
> missing error checking somewhere...

Invalid transformation operators just expand to nothing.

``The lyf so short, the craft so long to lerne.'' - Chaucer
		 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU    chet at case.edu    http://tiswww.cwru.edu/~chet/

More information about the Toybox mailing list