Andrea Grandi
Andrea Grandi

Reputation: 975

Why 'eval "MYVALUE=mystring" export MYVALUE' only works from bash and not zsh?

I'm trying to figure out why the following command only works from bash and not from zsh:

Bash:

bash-3.2$ eval "MYVALUE=mystring" export MYVALUE
bash-3.2$ echo $MYVALUE
mystring

Zsh:

➜  ~ eval "MYVALUE=mystring" export MYVALUE
➜  ~ echo $MYVALUE

➜  

I expected zsh to print mystring but instead it doesn't print anything.

It looks like export can't read the value which has just been parsed, but effectively eval is working, because if I run this other command using zsh:

➜  ~ eval "MYVALUE=mystring" env | grep MYVALUE
MYVALUE=mystring

it works as expected!

Can anyone please help me to figure out why the eval / export thing doesn't work with zsh but works with bash and how eventually make it work with zsh too? Thank you so much!

Upvotes: 1

Views: 2274

Answers (2)

Andrea Grandi
Andrea Grandi

Reputation: 975

After a bit of try and error and thanks to the hint from @glenn-jackman I can say that a possible solution that works with both bash and zsh is:

eval "MYVALUE=mystring"; export MYVALUE

Basically we need to add ; before the export

Upvotes: 1

user1934428
user1934428

Reputation: 22356

The difference between bash and zsh in this respect is not related to eval, but in a subtle difference related to export.

You execute eval with 3 parameter:

"MYVALUE=mystring" 
export 
MYVALUE

Now the zsh man page (at least of my zsh version) is a bit misleading in its description of what eval is doing when it is invoked with more than argument, but a simple experiment shows what is going on:

eval 'A=BBBBBB' 'printenv A'

outputs BBBBBB. In fact, eval seems to string its arguments together into a single string, but separates the pieces by a space. Hence in your case,

eval "MYVALUE=mystring" export MYVALU

is equivalent to

eval "MYVALUE=mystring export MYVALU"

which in turn is simply

MYVALUE=mystring export MYVALU

and here is a difference between bash and zsh:

While in both shells, a statement of the form

A=B C

executes C where in a modified environment where A is set to B, the bash export is a command and "sees" the modified environment. This means that in

A=B export A

the bash export command "sees" the setting of A and exports the variable. In zsh, the export is simply a keyword and the modified invironment is ignored.

Therefore, you need either two separate statements in zsh, for instance

eval "MYVALUE=mystring;" export MYVALUE

or rewrite it as

eval export "MYVALUE=mystring"

Of course this leaves still the question, why you are using eval in the first place.

Upvotes: 1

Related Questions