关联数组默认为本地数组

dav*_*ide 29 bash scope

默认情况下,关联数组在函数体内声明时似乎是局部的,它们应该是全局的.以下代码

#!/bin/bash

f() {
    declare -A map
    map[x]=a
    map[y]=b
}

f
echo x: ${map[x]} y: ${map[y]}
Run Code Online (Sandbox Code Playgroud)

产生输出:

x:  y:
Run Code Online (Sandbox Code Playgroud)

而这个

#!/bin/bash

declare -A map

f() {
    map[x]=a
    map[y]=b
}

f
echo x: ${map[x]} y: ${map[y]}
Run Code Online (Sandbox Code Playgroud)

产生输出:

x: a y: b
Run Code Online (Sandbox Code Playgroud)

是否可以在函数中声明全局关联数组?或者可以使用什么样的解决方案?

dav*_*ide 25

来自:Greg Wooledge
发送时间:2011年8月23日星期二06:53:27 -0700
主题:回复:YAQAGV(关于全局变量的另一个问题)

bash 4.2添加"declare -g"以在函数内创建全局变量.

谢谢格雷格!然而Debian Squeeze仍然有Bash 4.1.5


jor*_*anm 7

您已经使用declare -g回答了自己的问题.bash版本<4.2的解决方法是在函数外部声明数组.

f() {
   map[y] = foo
}

declare -A map
foo
echo "${map[y]}"
Run Code Online (Sandbox Code Playgroud)

  • 我自己的示例中明确显示了该选项。但是,当您需要在函数内“取消设置”然后“声明”相同的变量时,它不起作用。但是,对于 Bash &lt; 4.2 仍然存在一种解决方法,包括将变量声明从函数内部“回显”到可以访问主环境的外部“eval”。 (2认同)

it3*_*3xl 6

只是为了有一个完整且可运行的示例。

一个函数在其内部创建一个全局关联数组变量。
其他函数将值分配给数组变量。

bash 4.2 及以上版本

set -euf +x -o pipefail # There is no place for implicit errors in this script.

function init_arrays(){
    # FYI. Multiple array declarations are not a problem. You can invoke it multiple times.

    # The "-gA" switch is the trick for the global array declaration inside a function.
    declare -gA my_var
}

function do_work(){
    init_arrays

    my_var[$1]=OPPA
}

do_work some_key

echo ${my_var[some_key]}
echo It is expected to get OPPA value printed above
Run Code Online (Sandbox Code Playgroud)

通过 GNU bash 版本 4.4 进行测试...

苹果系统

macOS 上的bash有 3.2 版本 (02/2023)。如果从上面的 init_arrays 函数中删除注释,则
必须使用zsh 。

function init_arrays(){
    declare -gA my_var
}

function do_work(){
    init_arrays
    my_var[$1]=OPPA
}

do_work some_key; echo ${my_var[some_key]}
Run Code Online (Sandbox Code Playgroud)

重要笔记

(bash) 该declare -A命令实际上并不立即创建关联数组;它只是在变量名称上设置一个属性,该属性允许您将名称分配为关联数组。数组本身在第一次赋值之前并不存在(!!!)。


mem*_*lex 5

好的,4.2增加了"declare -g",但它对于关联数组来说是错误的,所以它还没有(还)回答这个问题.这是我的错误报告,并且Chet确认有下一个版本的修复程序.

http://lists.gnu.org/archive/html/bug-bash/2013-09/msg00025.html

但我偶然发现了一种解决方法,而不是声明数组并同时为它分配初始值,首先声明数组然后进行赋值.也就是说,不要这样做:

declare -gA a=([x]=1 [y]=2)
Run Code Online (Sandbox Code Playgroud)

但这反过来:

declare -gA a; a=([x]=1 [y]=2)
Run Code Online (Sandbox Code Playgroud)