通常从另一个脚本获取文件,我可以访问它的变量。
如果我从函数中获取脚本,则其变量不是全局变量,这似乎与联机帮助页相矛盾:
FUNCTION 函数的局部变量可以用 local 内置命令声明。通常,变量及其值在函数及其调用者之间共享。
source filename [arguments]在当前 shell 环境中从 filename 读取和执行命令
发生在我所有方便可用的版本中:3.2.57(1)-release (x86_64-apple-darwin17)、4.3.42(1)-release (x86_64-suse-linux-gnu) 和 4.3.48(1) -发布 (x86_64-pc-linux-gnu)
测试sourced.sh:
#!/bin/bash
echo $BASH_SOURCE $$ $SHLVL
declare -x FOO=bar
foo() { echo funfoo=$FOO $$ $SHLVL ; }
Run Code Online (Sandbox Code Playgroud)
测试top.sh:
#!/bin/bash
echo $BASH_SOURCE $$ $SHLVL
funcsource () { source ./test-sourced.sh ; }
echo ==== funcsource...
funcsource
echo foo=$FOO
foo
echo ==== source...
source ./test-sourced.sh
echo foo=$FOO
foo
Run Code Online (Sandbox Code Playgroud)
我看到了这个输出,但希望看到 funcsource 和 source 做同样的事情:
$ ./test-top.sh
./test-top.sh 1234 2
==== funcsource...
./test-sourced.sh 1234 2
foo=
funfoo= 1234 2
==== source...
./test-sourced.sh 1234 2
foo=bar 1234 2
funfoo=bar
Run Code Online (Sandbox Code Playgroud)
它是相同的 PID 和相同的 shell 级别,所以它看起来像是故意的行为。这是一个错误,还是我错过了什么?
更新:在source命令 DOES 给出它们的值后立即回显 $FOO 并在函数中运行 'foo' ,所以它们得到了那么远,但由于某种原因保持在函数作用域的本地。这似乎仍然与手册相矛盾。
这种行为的原因是因为您正在使用declare内置的shell。根据help declare:
在函数中使用时,
declare使 NAME 成为本地的,就像local命令一样。该-g选项禁止这种行为。
更改test-sourced.sh为 usedeclare -g而不是declare -x(将变量导出到环境)——或常规的 shell 变量赋值——应该显示预期的行为(变量是全局的):
#!/bin/bash
echo $BASH_SOURCE $$ $SHLVL
# Simple shell variable assignment (global by default)
FOO=bar
# Use declare to globally assign a value to the shell variable
declare -g FOO=bar
foo() { echo funfoo=$FOO $$ $SHLVL ; }
Run Code Online (Sandbox Code Playgroud)
如果您希望从该 shell 会话启动的未来子进程可以访问该变量,则将变量导出到环境中只会增加实用程序。如果这是您想要的,您可以使用以下任一 Bash 构造来确保变量是全局的和导出的:
export FOO=bar
declare -x -g FOO=bar
Run Code Online (Sandbox Code Playgroud)