bash 通过函数内部采购创建的数组具有局部作用域,但标量是全局的
bash arrays created by sourcing inside a function have local scope but scalars are global
考虑以下 bash 脚本:
#!/usr/bin/env /bin/bash
function sourcefile(){
source /tmp/srcfile
echo "Sourced array in func: ${sourcedarray[*]}"
echo "Sourced scalar in func: ${sourcedscalar}"
}
globalarray=([0]="xyzzy" [1]="kaboom")
globalscalar="argle"
cat >/tmp/srcfile <<EOF
export sourcedscalar="bargle"
export sourcedarray=([0]="foo" [1]="bar")
EOF
sourcefile
echo "Global array: ${globalarray[*]}"
echo "Global scalar: ${globalscalar}"
echo "Sourced array: ${sourcedarray[*]}"
echo "Sourced scalar: ${sourcedscalar}"
人们会合理地期望在输出中设置所有四个值,但至少在 bash 版本 3.2.57(1)-release
中(是的,是的,我知道:我们都为 Apple 的偏执狂买单)这是不是这样的:
Sourced array in func: foo bar
Sourced scalar in func: bargle
Global array: xyzzy kaboom
Global scalar: argle
Sourced array:
Sourced scalar: bargle
据我所知:
- 通过获取文件在函数中创建的标量变量在全局范围内创建
- 但是通过获取文件在函数中创建的数组变量是在 local 范围内创建的,导出它不会改变这一点
委婉地说这似乎不一致:有什么方法可以解决此问题?
正如评论中指出的那样,在更“最新”的 bash 版本中,这不再是问题。对于 4.3 及以下版本,我们发现以下内容:
首先,分配是否在源脚本中无关紧要;该功能有所作为。但是,单独的功能也不会导致您的问题。只有 function + export
的组合导致数组是局部的。
如果删除作业前面的 export
,一切正常。在您的示例中,您不必导出变量。实际上,没有办法导出数组,因为 posix.
中没有指定数组
如果您想创建一个全局变量并将其导出,请使用 declare -xg
而不是 export
。
#!/usr/bin/env bash
function sourcefile(){
source /tmp/srcfile
echo "Sourced array in func: ${sourcedarray[*]}"
echo "Sourced scalar in func: ${sourcedscalar}"
}
globalarray=([0]="xyzzy" [1]="kaboom")
globalscalar="argle"
cat >/tmp/srcfile <<EOF
declare -xg sourcedscalar="bargle"
# whether or not you use `-x` makes no difference for the environment
declare -xga sourcedarray=([0]="foo" [1]="bar")
EOF
sourcefile
echo "Global array: ${globalarray[*]}"
echo "Global scalar: ${globalscalar}"
echo "Sourced array: ${sourcedarray[*]}"
echo "Sourced scalar: ${sourcedscalar}"
考虑以下 bash 脚本:
#!/usr/bin/env /bin/bash
function sourcefile(){
source /tmp/srcfile
echo "Sourced array in func: ${sourcedarray[*]}"
echo "Sourced scalar in func: ${sourcedscalar}"
}
globalarray=([0]="xyzzy" [1]="kaboom")
globalscalar="argle"
cat >/tmp/srcfile <<EOF
export sourcedscalar="bargle"
export sourcedarray=([0]="foo" [1]="bar")
EOF
sourcefile
echo "Global array: ${globalarray[*]}"
echo "Global scalar: ${globalscalar}"
echo "Sourced array: ${sourcedarray[*]}"
echo "Sourced scalar: ${sourcedscalar}"
人们会合理地期望在输出中设置所有四个值,但至少在 bash 版本 3.2.57(1)-release
中(是的,是的,我知道:我们都为 Apple 的偏执狂买单)这是不是这样的:
Sourced array in func: foo bar
Sourced scalar in func: bargle
Global array: xyzzy kaboom
Global scalar: argle
Sourced array:
Sourced scalar: bargle
据我所知:
- 通过获取文件在函数中创建的标量变量在全局范围内创建
- 但是通过获取文件在函数中创建的数组变量是在 local 范围内创建的,导出它不会改变这一点
委婉地说这似乎不一致:有什么方法可以解决此问题?
正如评论中指出的那样,在更“最新”的 bash 版本中,这不再是问题。对于 4.3 及以下版本,我们发现以下内容:
首先,分配是否在源脚本中无关紧要;该功能有所作为。但是,单独的功能也不会导致您的问题。只有 function + export
的组合导致数组是局部的。
如果删除作业前面的 export
,一切正常。在您的示例中,您不必导出变量。实际上,没有办法导出数组,因为 posix.
如果您想创建一个全局变量并将其导出,请使用 declare -xg
而不是 export
。
#!/usr/bin/env bash
function sourcefile(){
source /tmp/srcfile
echo "Sourced array in func: ${sourcedarray[*]}"
echo "Sourced scalar in func: ${sourcedscalar}"
}
globalarray=([0]="xyzzy" [1]="kaboom")
globalscalar="argle"
cat >/tmp/srcfile <<EOF
declare -xg sourcedscalar="bargle"
# whether or not you use `-x` makes no difference for the environment
declare -xga sourcedarray=([0]="foo" [1]="bar")
EOF
sourcefile
echo "Global array: ${globalarray[*]}"
echo "Global scalar: ${globalscalar}"
echo "Sourced array: ${sourcedarray[*]}"
echo "Sourced scalar: ${sourcedscalar}"