Issue
I'm reading Richard Blum and Christine Bresnahan's "Linux Command Line and Shell Scripting Bible." In the section dealing with different special variables like $#
and $@
they point out that, although $#
contains the index of the final parameter, it cannot be used to short-circuit to accessing the final parameter, like so: ${$#}
. Instead, we're supposed to use ${!#}
. Not much explanation is given for why this is the case, only that it's so.
That's all well and good and I will remember that should I ever go to do something like this - but is there some deeper reason buried in the mechanics of bash (or even just features that are beyond the scope of an introductory text) to explain why ${$#}
doesn't work? I spent some time looking for an answer on the internet and couldn't uncover much. The man page for bash touched on it, but not in a way that made any sense to me.
Solution
Why can't we use ${$#} to get the last argument passed to a shell script?
We can't use ${$#}
to get the last arguments, because variable expansions are just not recursive ad the content of {
}
is just parsed by shell once. We can't use that, because it was never implemented. I think there is really not much explanation here, only that it is so.
Not much explanation is given for why this is the case, only that it's so.
While we can't explain why in physics, you could think we can explain why in programming. The only answer to "why", is "because it was invented this way". The person who wrote the (first) shell, wrote it to work that way, it got standardized and now all the standard shells work that way.
Most probably it was written that way, because it was easy to do. I think this is the best explanation we can get.
if I do indeed echo ${$#} I get a random number (when I tried it, I got 5138). Does this number have any significance at all?
echo $$
gives you PID of the current shell process.echo ${$}
also gives PID of the current shell process.${var#string}
removesstring
from the beginning of expansion fovar
- for example
a=1234; echo ${a#12}
removes12
from the beginning of1234
resulting in34
.
- for example
- The
${$#}
expands to the current pid like$$
and then the#
removes... "nothing" from the beginning of the variable, so it's the same as$$
.
See https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html the ${parameter#word}
part.
Remember to check your scripts with shellcheck https://www.shellcheck.net/ . Also check https://mywiki.wooledge.org/BashFAQ .
Answered By - KamilCuk Answer Checked By - Timothy Miller (WPSolving Admin)