[Toybox] bash continues to confuse me.

Rob Landley rob at landley.net
Wed Jun 17 10:22:05 PDT 2020

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}

Is going on? 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
  $ 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")


  $ echo ${!potato at walrus}

  $ echo ${!P at walrus}

  $ echo ${!P@}

  $ X=PATH
  $ echo ${!X@ }
  bash: ${!X@ }: bad substitution

  $ ABC=123
  $ echo ${!A at walrus}

  $ echo ${!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 @...?

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 @?

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

Anyway, I'm confused again. Did I miss something in the man page?

  $ echo ${!ABC:1:2 at Q}
  bash: !ABC: 2 at Q: value too great for base (error token is "2 at Q")
  $ echo ${!ABC:1:2 @Q}
  bash: !ABC: 2 @Q: syntax error: invalid arithmetic operator (error token is

Which to be honest is more like what I expected, it sees the : and goes "ah,
consume the remainder in THIS mode"...

  $ echo ${abc#23 at Q}

But if ANYTHING was going to recognize @Q at the end of another operation I'd
expect it to be : which already has to recognize further punctuation, but no:

  $ ABC=123; echo ${ABC:@Q}
  bash: ABC: @Q: syntax error: operand expected (error token is "@Q")


More information about the Toybox mailing list