I was doing something very simple like: v=5 echo "$v"
and expected it to print 5
. However, it does not. The value that was just set is not available for the next command.
I recently learnt that "In most shells, each command of a pipeline is executed in a separate SubShell". However, in this case both commands are being executed in the same subshell.
Why does this happen? Is there any way to have this working?
Full example:
$ v=1
$ v=5 echo "$v"
1 # I expected 5!
Let's look to the POSIX specification to understand why this behaves as it does, not just in bash but in any compliant shell:
2.10.2, Shell Grammar Rules
From rule 7(b), covering cases where an assignment precedes a simple command:
Thus, parsing this assignment is required for a POSIX-compliant shell.
2.9.1, Simple Commands
Thus: An assignment given in part of the prefix to a simple command must be exported, and must not impact the "current shell environment", unless the shell being invoked is a special built-in. Moreover, these steps shall follow redirections, which by nature must occur late in the command invocation process.
2.12, Shell Execution Environment
Thus: These variables are expanded by the subshell after fork and before exec'ing the command being invoked, and must -- by specification -- impact the child's environment alone.
Now, for some different behavior:
...benefits from the
sh
instance creating shell variables from its environment variables (as required in section 2.5.3 of the POSIX specification) on startup.It's worth noting, by the way, that the syntax you're asking about is for assignment within a simple command, as opposed to assignment within a subshell. You can control assignment in a subshell involved in a pipeline like so:
...which puts the assignment into the subshell running the first component of the pipeline (if your shell is indeed running that component in a subshell, which is undefined behavior inasmuch as POSIX is concerned; from the spec: "as an extension, however, any or all commands in a pipeline may be executed in the current environment").
Put simply, the "$v" is evaluated before the command is called while prepending "v=5" in front of the command modifies the environment of the command you're running.
As Charles Duffy said, you can add an intermediate 'sh' process that will evaluate the variable with a similar syntax but you probably want to do something a bit more elaborate and it'd be useful to know what if you still have troubles with it.
will add v=5 into the environment variables and then execute
echo $v
. The$v
refers to the shell variablev
which you have set to 1 in the first line.Adding the semi colon
v=5;echo $v
sets the shell variable to 5 and then executes the command after the semi-colon ieecho $v
and produces 5.Try this command:
and look at the environment.