通常从另一个脚本获取文件,我可以访问它的变量。
如果我从函数中获取脚本,其变量不是全局,这似乎与联机帮助页相矛盾:
功能可以使用local builtin命令声明函数本地的变量。通常,变量及其值在函数及其调用者之间共享。
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)-release(x86_64-pc-linux-gnu)
test-sourced.sh:
#!/bin/bash
echo $BASH_SOURCE $$ $SHLVL
declare -x FOO=bar
foo() { echo funfoo=$FOO $$ $SHLVL ; }
test-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
我看到了这个输出,但是期望看到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
它是相同的PID和相同的shell级别,所以它看起来像故意行为。这是一个错误,还是我错过了什么?
更新:回复$ FOO并在source
命令之后立即在函数中运行'foo'给出它们的值,所以它们已经到了那么远但由于某种原因保持在函数范围内。这仍然与手册相矛盾。
答案 0 :(得分:3)
出现这种行为的原因是因为你正在使用内置的declare
shell。根据{{1}}:
在函数中使用时,
help declare
会使NAME成为本地名称,与declare
一样 命令。local
选项会抑制此行为。
将-g
更改为使用test-sourced.sh
而不是declare -g
(将变量导出到环境中) - 或常规的shell变量赋值 - 应该显示预期的行为(变量是全局的) ):
declare -x
如果希望从该shell会话启动的未来子进程可以访问该变量,那么将该变量导出到环境只会添加实用程序。如果这是您想要的,您可以使用以下任一Bash结构来确保变量是全局变量和导出变量:
#!/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 ; }
答案 1 :(得分:0)
使用export
代替declare -x
,声明将变量范围限制为无法在外部显示。
#!/bin/bash
echo $BASH_SOURCE $$ $SHLVL
export FOO=bar #or FOO=bar
foo() { echo funfoo=$FOO $$ $SHLVL ; }