Bash阵列导出?

Rob*_*ino 7 bash

是否可以从函数中的单个语句声明和导出数组?

我目前的解决方法是先声明,然后再导出.

f() { foo=(1 2 3); export foo; }; f; export -p | grep foo=
declare -ax foo='([0]="1" [1]="2" [2]="3")'
Run Code Online (Sandbox Code Playgroud)

我观察到:

f() { export bar=(1 2 3); }; f; export -p | grep bar=
<no output>
Run Code Online (Sandbox Code Playgroud)

和:

f() { export baz="(1 2 3)"; }; f; export -p | grep baz=
declare -x baz="(1 2 3)" # not an array
Run Code Online (Sandbox Code Playgroud)

我使用 v3.2.48(1)-release而无法升级.


一些背景:

我有一个朋友,我正在尝试研究"一些"Django.

在命令行上他比我更无能,并且在OSX hackintosh上需要以下内容:

  • 启动交互式shell
  • 根据我的规范找到包含django bin目录的PATH变量
  • 找到一个更新的PYTHONPATH env var,可以看到各种django库
  • 一个很好的交互式ipython shell,在双击后开始输入命令
  • (棘手的)一个交互式的shell,一旦他从CTRB-D退出ipython就会回归

在Windows上,我将别名命令快捷方式,如cmd.exe,设置自定义环境变量并启动ipython.这样做:退出ipython后,仍然可以在命令解释器中找到自己.

OSX的标准bash是否可以实现这一点?我玩bash -c但很多东西都不起作用,比如改成目录,能够退出python并在终端等等.还用-s玩.

orm*_*aaj 5

您无法在Bash(或任何其他shell)中导出数组.Bash 永远不会将数组导出到环境中(直到某天可能实现,请参阅bugs联机帮助页中的部分).

这里有几件事情要发生.同样,-x在数组上设置属性是没有意义的,因为它实际上不会被导出.您看到这些结果的唯一原因是因为您在对数组进行本地化之前定义了数组,导致数组下拉到该名称已在本地(或全局范围)生成的下一个最外层范围.

所以要明确的是,无论何时使用声明命令,除非使用exportreadonly使用非数组赋值作为参数,否则总是创建本地,因为它们是POSIX,它不指定本地或数组.

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")'
Run Code Online (Sandbox Code Playgroud)

看来如果你给一个数组作为一个参数,export那么Bash将使它像任何其他声明命令一样本地化.基本上不要export用来定义数组.export是一个POSIX内置而且其行为是未定义的阵列,这可能是为什么bash的只是把它当作仿佛你已经使用typeset -ax a=(1 2 3).使用typeset,localdeclare.真的没有办法知道什么是"正确的",甚至与其他炮弹相比.ksh93是唯一一个接受数组赋值作为声明命令参数的人,它的行为与Bash不一致.

要理解的重要一点是环境与它无关,当你尝试用POSIX-only命令做非标准的事情时,你只是在玩当地人的怪癖.

为了实际获得你想要的效果,你可以使用typeset -p.

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

typeset -a arr
eval "$(f arr)"
typeset -p arr
Run Code Online (Sandbox Code Playgroud)

Bash保证你会得到正确的结果,但我发现这不是很有用,很少使用这种方法.它通常是更好的只是让来电者定义本地和使用动态范围不工作(因为你已经发现了......只是做没有出口).

在Bash 4.3中你可以使用typeset -n,这是处理这个问题的最正确方法.