如果源脚本在函数中运行,为什么bash变量不是全局变量? [英] Why are bash variables not global if sourced script runs in a function?

查看:57
本文介绍了如果源脚本在函数中运行,为什么bash变量不是全局变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通常可以从另一个脚本中获取文件,我可以访问其变量.

Sourcing a file normally from another script, I can access its variables.

如果我从函数中获取脚本,则其变量不会全局,这似乎与手册页相抵触:

If I source a script from within a function, its variables aren't global, which seems to contradict the manpage:

功能可以使用本地内置命令声明函数本地变量.通常,变量及其值在函数及其调用者之间共享.

FUNCTION Variables local to the function may be declared with the local builtin command. Ordinarily, variables and their values are shared between the function and its caller.

源文件名[参数] 在当前Shell环境中从文件名读取并执行命令

source filename [arguments] Read and execute commands from filename in the current shell environment

发生所有我方便使用的版本:3.2.57(1)-发行版(x86_64-apple-darwin17),4.3.42(1)-发行版(x86_64-suse-linux-gnu)和版本4.3.48(1)-发布(x86_64-pc-linux-gnu)

Happens with all my conveniently available versions: 3.2.57(1)-release (x86_64-apple-darwin17), 4.3.42(1)-release (x86_64-suse-linux-gnu), and version 4.3.48(1)-release (x86_64-pc-linux-gnu)

test-sourced.sh:

test-sourced.sh:

#!/bin/bash
echo $BASH_SOURCE $$ $SHLVL
declare -x FOO=bar
foo() { echo funfoo=$FOO $$ $SHLVL ; }

test-top.sh:

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都做同样的事情:

I see this output, but expected to see both funcsource and source do the same thing:

$ ./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和相同的外壳程序级别,因此看起来像是故意的行为.这是一个错误,还是我缺少什么?

It's the same PID and the same shell level, so it looks like deliberate behaviour. Is this a bug, or am I missing something?

更新:在 source 命令提供值之后,立即在函数中回显$ FOO并运行'foo',因此它们的作用已经达到了极限,但由于某种原因而保留在该函数的本地范围.似乎仍然与手册相抵触.

Update: echoing $FOO and running 'foo' in the function immediately after the source command DOES give their values, so they're getting that far but are for some reason kept local to the function scope. Which still seems to contradict the manual.

推荐答案

出现此问题的原因是因为您使用的是内置的 declare shell.根据帮助声明:

The reason for this behaviour is because you’re using the declare shell builtin. According to help declare:

在函数中使用时, declare 使名称成为本地名称,与 local 命令. -g 选项可抑制此行为.

When used in a function, declare makes NAMEs local, as with the local command. The -g option suppresses this behavior.

更改 test-sourced.sh 以使用 declare -g 代替 declare -x (将变量导出到环境)–或常规的shell变量赋值–应该显示预期的行为(其中变量为全局变量):

Changing test-sourced.sh to use declare -g instead of declare -x (export the variable to the environment) – or a regular shell variable assignment – should show the expected behaviour (where the variable is global):

#!/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 ; }


仅当您希望该Shell会话启动的将来子进程可以访问该变量时,才将变量导出到环境中会增加实用程序.如果这是您想要的,则可以使用以下两种Bash构造之一来确保该变量既是全局变量又是导出变量:


Exporting the variable to the environment only adds utility if you want the variable to be accessible to future child processes started from that shell session. If this is what you want, you can use either of the following Bash constructs to ensure the variable is both global and exported:

export FOO=bar
declare -x -g FOO=bar

这篇关于如果源脚本在函数中运行,为什么bash变量不是全局变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆