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