如何为 shell 命令设置环境变量
How to set environment variables for a shell command
我经常在 node.js 程序中看到这个命令:NODE_ENV=test node app.js
它将 NODE_ENV 变量设置为测试和工作。我也在此处阅读 https://en.wikipedia.org/wiki/Environment_variable 这应该适用于任何 shell 命令,但是 运行 我自己进行了一些测试,这是我看到的
$ HELLO="WORLD"
$ HELLO="MARS" echo "$HELLO"
WORLD
$
我希望它能打印 MARS
。我在这里遗漏了什么吗?
语法 VAR=value command
意味着将在环境变量 VAR
设置为 VALUE
的情况下调用该命令,这将仅适用于该命令的范围。
但是,当您使用命令行时:
HELLO="MARS" echo "$HELLO"
shell首先解释"$HELLO"
参数,确定是WORLD
,然后它实际做的是运行:
HELLO="MARS" echo "WORLD"
所以 echo 可能设置了 HELLO
变量,但它不会影响它打印的内容 - 它之前已经被解释过。
正在做
HELLO="MARS"; echo "$HELLO"
完全在做其他事情。首先它在当前 shell 中将 HELLO
设置为 MARS
,然后继续解释 echo
命令。此时 HELLO
包含 MARS
,而不是 WORLD
。但这是完全不同的效果 - 变量 HELLO
保留值 MARS
,在没有 ;
.
的命令中情况并非如此
你的问题是 echo
只是一个糟糕的演示选择。你可以做其他的演示来证明 HELLO
被正确更改:
HELLO="MARS" eval 'echo $HELLO'
在这种情况下,shell 不会解释 $HELLO
,因为它在单引号内的字符串中。它首先将 MARS
放入 HELLO
,然后使用该变量集调用 eval 'echo $HELLO'
。 eval
命令和 运行 echo $HELLO
,你会得到你期望的输出。
此语法最适用于不将给定变量用作命令行的一部分,而是在内部使用它的情况。
其他答案都对,这里再细化一下:
在bash中定义以空格分隔的变量列表实际上有2种情况,无论是否以命令结束。
VAR1=value1 VAR2=value2 ... VARn=valuen command arg1 arg2 ... argn
和
VAR1=value1 VAR2=value2 ... VARn=valuen
不要以同样的方式导出 VAR1 ... VARn。
在第一种情况下,VAR1 ... VARn 将仅为命令设置,然后不会导出到当前 shell。
在第二种情况下,VAR1 ... VARn 将改变电流 shell。
然后(注意 ';' 与使用新行非常相似)
HELLO=WORLD
HELLO=MARS echo "i don't export HELLO."
echo "HELLO=$HELLO"
会显示
i don't export HELLO.
HELLO=WORLD
和
HELLO=WORLD
HELLO=MARS ; echo "i did export HELLO."
echo "HELLO=$HELLO"
会显示
i did export HELLO.
HELLO=MARS
我经常在 node.js 程序中看到这个命令:NODE_ENV=test node app.js
它将 NODE_ENV 变量设置为测试和工作。我也在此处阅读 https://en.wikipedia.org/wiki/Environment_variable 这应该适用于任何 shell 命令,但是 运行 我自己进行了一些测试,这是我看到的
$ HELLO="WORLD"
$ HELLO="MARS" echo "$HELLO"
WORLD
$
我希望它能打印 MARS
。我在这里遗漏了什么吗?
语法 VAR=value command
意味着将在环境变量 VAR
设置为 VALUE
的情况下调用该命令,这将仅适用于该命令的范围。
但是,当您使用命令行时:
HELLO="MARS" echo "$HELLO"
shell首先解释"$HELLO"
参数,确定是WORLD
,然后它实际做的是运行:
HELLO="MARS" echo "WORLD"
所以 echo 可能设置了 HELLO
变量,但它不会影响它打印的内容 - 它之前已经被解释过。
正在做
HELLO="MARS"; echo "$HELLO"
完全在做其他事情。首先它在当前 shell 中将 HELLO
设置为 MARS
,然后继续解释 echo
命令。此时 HELLO
包含 MARS
,而不是 WORLD
。但这是完全不同的效果 - 变量 HELLO
保留值 MARS
,在没有 ;
.
你的问题是 echo
只是一个糟糕的演示选择。你可以做其他的演示来证明 HELLO
被正确更改:
HELLO="MARS" eval 'echo $HELLO'
在这种情况下,shell 不会解释 $HELLO
,因为它在单引号内的字符串中。它首先将 MARS
放入 HELLO
,然后使用该变量集调用 eval 'echo $HELLO'
。 eval
命令和 运行 echo $HELLO
,你会得到你期望的输出。
此语法最适用于不将给定变量用作命令行的一部分,而是在内部使用它的情况。
其他答案都对,这里再细化一下:
在bash中定义以空格分隔的变量列表实际上有2种情况,无论是否以命令结束。
VAR1=value1 VAR2=value2 ... VARn=valuen command arg1 arg2 ... argn
和
VAR1=value1 VAR2=value2 ... VARn=valuen
不要以同样的方式导出 VAR1 ... VARn。
在第一种情况下,VAR1 ... VARn 将仅为命令设置,然后不会导出到当前 shell。
在第二种情况下,VAR1 ... VARn 将改变电流 shell。
然后(注意 ';' 与使用新行非常相似)
HELLO=WORLD
HELLO=MARS echo "i don't export HELLO."
echo "HELLO=$HELLO"
会显示
i don't export HELLO.
HELLO=WORLD
和
HELLO=WORLD
HELLO=MARS ; echo "i did export HELLO."
echo "HELLO=$HELLO"
会显示
i did export HELLO.
HELLO=MARS