简体   繁体   中英

bash arrays created by sourcing inside a function have local scope but scalars are global

Consider the following bash script:

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

One would reasonably expect all four values to be set in the output, but at least with bash version 3.2.57(1)-release (yes, yes I know: we all pay for Apple's paranoia) that is not the case:

Sourced array in func: foo bar
Sourced scalar in func: bargle
Global array: xyzzy kaboom
Global scalar: argle
Sourced array:
Sourced scalar: bargle

As far as I can tell:

  • a scalar variable created in a function by sourcing a file is created in global scope
  • but an array variable created in a function by sourcing a file is created in local scope, and exporting it does not change this

This seems inconsistent to put it mildly: is there some way to work around this behavior?

As pointed out in the comments, in more "recent" version of bash this is no longer a problem. For versions 4.3 and below we find the following:

First of all, whether or not the assignment is in a sourced script plays no role; the function makes a difference. However, the function alone also doesn't cause your problem. Only the combination of function + export causes the array to be local.

If you remove the export in front of the assignment, everything works fine. In your example you don't have to export the variables anyway. Actually, there is no way to export an array as arrays are not specified in posix.

If you want to create a global variable and also export it then use declare -xg instead of 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}"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM