0

I want to assign one or multiple variables at the beginning of a command line in my shell to reuse it in the command invocation. I'm confused of how my shell behaves and want to understand what is happening.

I'm using ZSH but am also interested what the "standard" posix behavior is.

1: % V=/ echo $V   # echo is a shell built-in?!?

expected: /. actual: ""

2: % V=/ ls $V   # ls is a command

expected: ls /. actual: ls

3: % V=/ ; echo $V

expected: "". actual: /

Here I thought that the semicolon would be equivalent to a new shell line and that I'd need export.

4: % V=/ ; ls $V

expected: ls. actual: ls /

I'm mostly surprised by lines 1 and 2. Is there any ZSH settings that could cause this or do I just start to use a semicolon to use variables in this way?

Thomas Koch
  • 2,833
  • 2
  • 28
  • 36
  • 1
    `echo` isn't using the environment. It doesn't even know a variable is being used; it gets the value of `V` as its argument, not the string `$V`. – chepner May 24 '20 at 19:57
  • 1
    I think I found the perfect answer: https://stackoverflow.com/a/10939280/240976 – Thomas Koch May 24 '20 at 21:16

2 Answers2

1

Variable expansion happens before the command is run, i.e. before the value is assigned to the variable in lines 1 and 2.

export is needed when you need to export the variable to a subshell. A semicolon doesn't introduce a subshell, but causes the assignment to be run before the next command, so the shell now expands the variable by its new value.

choroba
  • 231,213
  • 25
  • 204
  • 289
0

Your line 1 would work if you would allow the variable expansion to occur inside the echo and don't force it, before echo gets a chance to run, for instance by

V=/ zsh -c 'echo $V'

or by

V=/ eval 'echo $V'

It doesn't matter that echo is a builtin command. The same idea applies to every command.

Since commands can be separated either by semicolons or by linefeeds, your line 3 is equivalent to

V=/
echo $V

which makes it obvious, why the substitution works in this case.

user1934428
  • 19,864
  • 7
  • 42
  • 87