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?
- 349,597
- 67
- 533
- 578
- 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 Answers
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.
- 8,841
- 11
- 24
- 39
-
1And 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
-
1Well, 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
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?
- 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
-
1It 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