Bash array export?

bash

Solution

You can't export an array in Bash (or any other shell). Bash will never export an array to the environment (until maybe implemented someday, see the `bugs` section in the manpage).

There are a couple things going on here. Again, setting the `-x` attribute on an array is nonsensical because it won't actually be exported. The only reason you're seeing those results is because you defined the array before localizing it, causing it to drop down to the next-outermost scope in which that name has been made local (or the global scope).

So to be clear, whenever you use a declaration command, you're always creating a local except when you use `export` or `readonly` with a non-array assignment as an argument, because these are POSIX, which doesn't specify either locals or arrays.

function f {
    typeset -a a # "a" is now local to "f"
    g
    printf 'Now back in "f": %s\n' "$(typeset -p a)"
}

function g {
    a=(1 2 3)                               # Assigning f's localized "a"
    typeset -a a                            # A new local a
    printf 'In "g": %s\n' "$(typeset -p a)" # g's local is now empty.
    a=(a b c)                               # Now set g's local to a new value.
    printf 'Still in "g": %s\n' "$(typeset -p a)"
}

f

# In "g": declare -a a='()'
# Still in "g": declare -a a='([0]="a" [1]="b" [2]="c")'
# Now back in "f": declare -a a='([0]="1" [1]="2" [2]="3")'

It seems if you give an array as an argument to `export` then Bash will make it local like any other declaration command. Basically don't use `export` to define an array. `export` is a POSIX builtin and its behavior is undefined for arrays, which is probably why bash just treats it as though you had used `typeset -ax a=(1 2 3)`. Use `typeset`, `local`, or `declare`. There's really no way to know what's "correct", or even compare with other shells. ksh93 is the only other that accepts array assignments as arguments to declaration commands, and its behavior doesn't agree with Bash.

The important thing to understand is that the environment has nothing to do with it, you're just playing with the quirks of locals when trying to do nonstandard things with POSIX-only commands.

In order to actually get the effect you want, you may use `typeset -p`.

function f {
    typeset -a "${1}=(1 2 3)"
    typeset -p "$1"
}

typeset -a arr
eval "$(f arr)"
typeset -p arr

Bash guarantees you'll get out the correct result, but I find this isn't very useful and rarely use this approach. It's usually better to just let the caller define a local and use dynamic scope do the work (as you've already discovered... just do it without exporting).

In Bash 4.3 you can use `typeset -n`, which is really the most correct way to handle this.

Problem

Is it possible to declare and export a bash array from a single statement within a function? My current workaround is to first declare, then to export. ``` f() { foo=(1 2 3); export foo; }; f; export -p | grep foo= declare -ax foo='([0]="1" [1]="2" [2]="3")' ``` I observe that: ``` f() { export bar=(1 2 3); }; f; export -p | grep bar= <no output> ``` and: ``` f() { export baz="(1 2 3)"; }; f; export -p | grep baz= declare -x baz="(1 2 3)" # not an array ``` I use bash v3.2.48(1)-release and can't upgrade. Some background: I have a friend with whome I am trying to study "some" Django. He's more clueless than me at the command line and needs the following, on OSX hackintosh: - launch an interactive shell - find the PATH variable including the django bin dir, as per my specification - find an updated PYTHONPATH env var, with the various django libs visible - a nice interactive ipython shell to start typing commands in after double-clicking - (tricky) an interactive shell to fall back to once he CTRL-D exits from ipython On Windows, I would alias a command shortcut, like cmd.exe, set custom environment variables and start ipython. This works: after exiting ipython one still finds oneself in a command interpreter. Is this possible at all with OSX's standard bash? I played with bash -c but many things don't work, like changing into a directory, being able to exit python and stay in a terminal, etc. Also played with -s.

Original source