2

Suppose that parameter=value is an internal variable in bash. When I try ${#parameter} in bash it returns a 5. But when I try, for instance, ${##parameter} or ${###parameter} it always give back 0 in return. Why it does not say that it is a substitution error as in other cases?

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Glitch
  • 155
  • 1
  • 9
  • It doesn't always return `0`, it returns the value of `$#`. In this case, the variable's value was evidently 0. – tripleee Feb 09 '20 at 16:24

2 Answers2

3

Short version

You could express ${##parameter} as:

x=$#
${x#parameter}

and ${###parameter} as:

x=$#
${x##parameter}

You are performing a prefix removal on $# (number of arguments passed to a script / function).


Longer version

If parameter has any special meaning, it would be likely specific to your environment.

$ echo \""${parameter}"\"
""

or even:

$ set -u
$ echo \""${parameter}"\"
bash: parameter: unbound variable

Now with that out of the way, quick look into docs:

${#parameter}

The length in characters of the expanded value of parameter is substituted.

So with variable parameter not being set:

$ echo ${#parameter}
0

or with set -u:

$ echo ${#parameter}
bash: parameter: unbound variable

Additional # changed meaning to Remove matching prefix pattern. using: ${parameter#word} or ${parameter##word} syntax on ${#}, i.e. number of argument passed to a script/function. Good way to see and understand that behavior would be:

$ f() { echo -n "$# " ; echo ${##parameter}; }
$ f
0 0
$ f a b c
3 3

As you see in first call ${#} was 0 and (and attempting to strip prefix "parameter" does nothing to it really) and the second call value of ${#} is 3.

Prefix removal, the different between # and ## is, when matching patterns whether shorted or longest match is stripped.

Ondrej K.
  • 8,841
  • 11
  • 24
  • 39
  • 1
    And to further emphasize how the meaning of `#` depends on context, `${####param}` would be parsed as an attempt to strip the longest prefix (with `##`) matching `#param` from the value of `$#`. – chepner Feb 09 '20 at 16:24
  • 1
    Well, bottom line really is, since `$#` will be a decimal number representaiton, any removal of `someString` prefix is essentially a `nop`. ;) – Ondrej K. Feb 09 '20 at 16:27
  • Right; I'm just pointing out that `#` can serve as a parameter name, (part of) an expansion operator, and part of the argument to that operator all in the same expression (regardless of whether the operation does anything to the value). – chepner Feb 09 '20 at 16:49
0

Because ## is a special operator that removes a prefix. See for instance here: What is the meaning of the ${0##...} syntax with variable, braces and hash character in bash?

Hellmar Becker
  • 2,824
  • 12
  • 18
  • But, if it removes a prefix, this syntax ```echo ${##param}``` (supposing param is unbound) should print nothing but yet it prints 0. – Glitch Feb 09 '20 at 16:13
  • 1
    It does not work on `param` it works on `$#` and tries to strip `"param"` hence it's not trying to expand (access) variable of name `param` or whatever follows the `#`/`##`. – Ondrej K. Feb 09 '20 at 16:15