31

How can we prevent parameter expansion? Does the Bash's Manual mention this somewhere? I'd appreciate if you could help me to locate where it is mentioned there.

For example,

$ b=1
$ echo $b
1

When the bash interpreter interprets echo $b, the parameter expansion $b happens before running echo $b. So there is no need to make b a environment variable of the shell process, in order to be passed to the subprocess for echo $b.

For comparison, consider another example from https://unix.stackexchange.com/a/261406/674

$ b=1
$ c=$(b=2; echo $b)
$ echo $c
2

In the original shell, when the bash interpreter interprets c=$(b=2; echo $b), it doesn't expand $b using the value 1.

In the subshell of the command substitution, when the bash interpreter interprets b=2; echo $b, it expands $b using the value 2.

What prevents the parameter expansion $b in the original shell, and leaves the parameter expansion $b till the subshell?

Quotes can prevent parameter expansions, e.g. "$b". But here there are no quotes around the parameter expansion. Does command substitution prevent parameter expansion in it?

Tim
  • 101,790
  • in the subshell, between ( and ) you have assigned b a value of 2 and echoed it out. The output from this subshell became the value of the variable c. The b=1 from the first line has no importance in the subshell. Is there a confusion here that I can not see ? – MelBurslan Feb 11 '16 at 18:44
  • 1
    Why do you expect the echo $b to be echo 1 if it was assigned 2 just before the echo? – RealSkeptic Feb 11 '16 at 18:46
  • @cuonglm: do you mean command substituion prevent parameter expansion in the original shell? Are there other similar cases? – Tim Feb 12 '16 at 08:54

1 Answers1

50

You have mistaken, double quotes "$b" does not prevent parameter expansion, it prevents pathname expansion (aka globbing) and fields splitting.

If you want to prevent parameter expansion, you need to use quoting, like single quote '$b' or escaping \$b:

$ echo '$b'

or:

$ echo \$b

then $b is output literally.


In the example, there's nothing to prevent parameter expansion.

When the shell read the input c=$(b=2; echo $b), it performs token recognition, saw that $( is the token for command substitution. So it treats the rest of string between $( and ) to be interpreted in the subshell created by command substitution, not the current shell.

Alexis Wilke
  • 2,857
cuonglm
  • 153,898
  • 1
    Yeah; the bash is just an interpreter. It follows the rules it is programmed by, so there could be exceptions - like evaluating everything except for given context. This is common in all(or almost all) languages, nothing strange. It just makes sense. Also, bash isn't implemented in bash, so it's not like they had to use magic tricks to make this work. – MatthewRock Feb 12 '16 at 09:07
  • It is absolutely necessary to apply this method for escaping expansion when passing text to a file from a script. This worked properly for me when using "<<END_TEXT" on a string that contained variables within it. – suprematis Nov 06 '20 at 20:42
  • 1
    @suprematis: actually that's not necessary; if you quote the delimiter-word or any part of it, like <<'END' or <<'E'ND or <<\END, then no expansions are done in the heredoc body. See https://www.gnu.org/software/bash/manual/html_node/Redirections.html#Here-Documents . – dave_thompson_085 Feb 20 '22 at 01:41