我有一个bash script
名为VAR_A
我也有一个当地人env variable
叫VAR_A
调用bash script
命令:
echo ${VAR_A}
我无法将脚本中的变量更改为其他名称,但我可以更改脚本调用命令的方式echo
。
如何修改echo
命令以确保它打印本地命令env variable
而不是脚本中提供的命令?
UPDATE FOR CLARITY:
情况:
用户有一个现有.bashrc
文件,在登录时设置:
VAR_A="someValue"
export VAR_A
这允许用户:
~]$ echo ${VAR_A}
someValue
我有一些 bash 脚本的配置文件
VAR_A="someOtherValue"
我有一个 bash 脚本:
#!/bin/bash
. ../configuration # imports config file with some values
# do stuff
echo ${VAR_A}
从终端(作为登录用户的 bash shell)执行脚本会打印:
~]$ ./run_script.sh
someOtherStuff
我需要它来打印:
~]$ ./run_script.sh
someStuff
答案1
shell 变量是从每个 shell 中的环境变量初始化的,你无法绕过这一点。
当 shell 启动时,对于它接收到的每个具有有效名称作为 shell 变量的环境变量,shell 都会为相应的 shell 变量分配相应的值。例如,如果您的脚本启动为:
env VAR_A=xxx your-script
(并且有一个#!/bin/bash -
she-bang),env
将执行/bin/bash
并传递VAR_A=xxx
给该 bash 命令,并将bash
为其变量分配$VAR_A
value xxx
。
在 Bourne shell 和 C-shell 中,如果为该 shell 变量分配一个新值,它不会影响传递给该 shell 后续执行的命令的相应环境变量,您必须使用export
或setenv
来实现这一点(但请注意在 Bourne shell 中,如果您unset
使用变量,它会删除 shell 变量和环境变量)。
在:
env VAR=xxx sh -c 'VAR=yyy; other-command'
(sh
是 Bourne shell,而不是现代 POSIX shell)或者:
env VAR=xxx csh -c 'set VAR = yyy; other-command'
other-command
VAR=xxx
在其环境中接收,而不是VAR=yyy
,您需要编写它:
env VAR=xxx sh -c 'VAR=yyy; export VAR; other-command'
或者
env VAR=yyy csh -c 'setenv VAR yyy; other-command'
为了在其环境中other-command
接收。VAR=yyy
然而,ksh
(结果是 POSIX,然后bash
是所有其他现代的类似 Bourne 的 shell)打破了这一点。
启动时那些现代 shell绑定将它们的shell变量添加到相应的环境变量中。
这意味着脚本可能仅通过设置其中一个变量来破坏环境,即使它不导出它。有些 shell 甚至会删除它无法映射到 shell 变量的环境变量(这就是为什么建议仅使用 shell 可映射的变量名称作为环境变量名称)。
这就是为什么按照惯例,所有大写变量都应该保留给环境变量的主要原因。
为了解决这个问题,如果您希望脚本执行的命令接收与解释脚本的 shell 接收到的环境相同的环境,则需要以某种方式存储该环境。您可以通过添加以下内容来做到这一点:
my_saved_env=$(export -p)
在脚本的开头,然后使用以下命令运行命令:
(eval "$my_saved_env"; exec my-other-command and its args)
在bosh
和mksh
贝壳中,当地的函数中的变量不会破坏环境变量(只要你不破坏export
环境变量),但请注意,使用一些特殊变量(例如HOME
for cd
、PATH
用于可执行文件查找...)的 shell 内置函数将使用壳(本地)变量,而不是环境变量。
$ env VAR=env mksh -c 'f() { local VAR=local; echo "$VAR"; printenv VAR; }; f'
local
env
答案2
VAR_A
您可以通过添加一行来使变量只读:
readonly VAR_A
在脚本的顶部。这将导致 的VAR_A
值为保留根据您当地的环境。
readonly: readonly [-aAf] [name[=value] ...] or readonly -p
Mark shell variables as unchangeable. Mark each NAME as read-only; the values of these NAMEs may not be changed by subsequent assignment. If VALUE is supplied, assign VALUE before marking as read-only. Options: -a refer to indexed array variables -A refer to associative array variables -f refer to shell functions -p display a list of all readonly variables and functions An argument of `--' disables further option processing. Exit Status: Returns success unless an invalid option is given or NAME is invalid.
下面的例子应该可以清楚地说明:
$ export FOO="somevalue" # environment variable FOO set to somevalue
$ cat test # test script
echo $FOO # print the value of FOO
readonly FOO # set FOO to local
FOO="something" # attempt to modify FOO
echo $FOO # print the value of FOO -- you would see the value that was inherited from the environment
$ bash test
somevalue
test: line 3: FOO: readonly variable
something
答案3
如果您想打印当地的变量VAR_A
,必须在其局部范围内调用,否则,它将打印全局变量的值VAR_A
:
#! /bin/bash
VAR_A="I'm global"
function lexical() {
local VAR_A="I'm lexical"
echo $VAR_A
}
echo -n "Global VAR_A: "
echo $VAR_A
echo -n "Lexical VAR_A: "
lexical
运行:
$ ./test.sh
Global VAR_A: I'm global
Lexical VAR_A: I'm lexical
您可以local
从以下页面阅读有关 bash 的更多信息man
:
local [option] [name[=value] ...]
For each argument, a local variable named name is created, and
assigned value. The option can be any of the options accepted
by declare. When local is used within a function, it causes the
variable name to have a visible scope restricted to that func‐
tion and its children. With no operands, local writes a list of
local variables to the standard output. It is an error to use
local when not within a function. The return status is 0 unless
local is used outside a function, an invalid name is supplied,
or name is a readonly variable.
答案4
发生的情况是配置文件VAR_A
正在覆盖VAR_A
来自.bashrc
.
因此,解决方案本身如下:在获取配置文件之前,保存 的内容VAR_A
,如下所示。
VAR_A_sav=${VAR_A} # assuming that VAR_A_sav does NOT exist in configuration
. ../configuration # that is, you must choose a name not existing in config.
VAR_A=${VAR_A_sav}