bash 4.x assoc 数组在接收函数中丢失键

标签 bash shell hashtable associative-array

我正在尝试将一个关联数组从一个函数传递到另一个函数,并且正在丢失命名索引键(例如,文件路径,在下面的示例中进行搜索),尽管传入的数组可以使用索引 0、1 正确访问其元素。我一定是 bash 语法出了点小问题,但不太清楚在哪里。任何帮助表示赞赏。

使用来自 Ubuntu 14.04 的 GNU bash,版本 4.3.8 下面是 bash 代码示例,底部是输出

#! /bin/bash

function test_function {

    func_data=("${@}")
    # without brackets above cannot access func_data[1]

    # local ${!func_data}
    # the above local statement does not seem to help either way

    echo ""
    for K in "${!func_data[@]}"; do echo $K; done

    echo ""
    echo "func_data           : ${func_data}"
    echo "func_data[filepath] : ${func_data[filepath]}"
    echo "func_data[search]   : ${func_data[search]}"
    # all three echos above output first element of array, 
    # which is 'style "default" {' during first loop

    # Can access array elements 0, 1 but no longer via filepath, search
    echo "func_data[0]        : ${func_data[0]}"
    echo "func_data[1]        : ${func_data[1]}"

    echo "!func_data[@]       : ${!func_data[@]}"
    # echo above outputs '0 1' so indexes now are now zero based?
    echo "func_data[@]        : ${func_data[@]}"
    # echo above outputs all array elements 'style "default" { ~/.gtkrc-2.0'
}

# In BASH, local variable scope is the current function and every 
# child function called from it, so provide a function main to
# make it possible to utilize variable scope to fix issues

function main {

    echo ""
    declare -A gtkrc2=()
    gtkrc2[filepath]="~/.gtkrc-2.0"
    gtkrc2[search]="style \"default\" {"
    echo "gtkrc2 filepath : ${gtkrc2[filepath]}"
    echo "gtkrc2 search   : ${gtkrc2[search]}"
    test_function "${gtkrc2[@]}"

    echo ""
    declare -A gtkcss=()
    gtkcss[filepath]="~/.config/gtk-3.0/gtk.css"
    gtkcss[search]=".scrollbar {"
    echo "gtkcss filepath : ${gtkcss[filepath]}"
    echo "gtkcss search   : ${gtkcss[search]}"
    test_function "${gtkcss[@]}"
}

main

------------ 输出------------

gtkrc2 filepath : ~/.gtkrc-2.0
gtkrc2 search   : style "default" {

func_data           : style "default" {
func_data[filepath] : style "default" {
func_data[search]   : style "default" {
func_data[0]        : style "default" {
func_data[1]        : ~/.gtkrc-2.0
!func_data[@]       : 0 1
func_data[@]        : style "default" { ~/.gtkrc-2.0

gtkcss filepath : ~/.config/gtk-3.0/gtk.css
gtkcss search   : .scrollbar {

func_data           : .scrollbar {
func_data[filepath] : .scrollbar {
func_data[search]   : .scrollbar {
func_data[0]        : .scrollbar {
func_data[1]        : ~/.config/gtk-3.0/gtk.css
!func_data[@]       : 0 1
func_data[@]        : .scrollbar { ~/.config/gtk-3.0/gtk.css

最佳答案

这可能是也可能不是执行此操作的“正确”方法,但这是我能想到的最佳方法。欢迎其他人提出任何建议:

function test_function {
    arrname=$1
    idxlist="$2"

    echo ""
    echo "Array passed=$arrname"
    for idx in $idxlist; do
        elemname=$arrname[$idx]
        echo "idx=$idx, elem=${!elemname}"

    done
}

# In BASH, local variable scope is the current function and every 
# child function called from it, so provide a function main to
# make it possible to utilize variable scope to fix issues

function main {

    echo ""
    declare -A gtkrc2=()
    gtkrc2[filepath]="~/.gtkrc-2.0"
    gtkrc2[search]="style \"default\" {"
    echo "gtkrc2 filepath : ${gtkrc2[filepath]}"
    echo "gtkrc2 search   : ${gtkrc2[search]}"
    test_function gtkrc2 "${!gtkrc2[*]}"

    echo ""
    declare -A gtkcss=()
    gtkcss[filepath]="~/.config/gtk-3.0/gtk.css"
    gtkcss[search]=".scrollbar {"
    echo "gtkcss filepath : ${gtkcss[filepath]}"
    echo "gtkcss search   : ${gtkcss[search]}"
    test_function gtkcss "${!gtkcss[*]}"
}

main

特别是:

  • 为了将每个关联数组传递给函数,我们传递数组的名称及其索引列表
  • 在函数内部,数组名和索引列表取自位置参数
  • 然后我们可以遍历索引列表并获得每个元素的相应值。这是通过首先生成元素的名称,然后使用 ! indirection modifier 来完成的。获得实际值(value)。

this question 中描述了这种数组间接寻址技术。 , 但只处理索引数组,不处理关联数组;传递索引列表是我能想到的一种方法,可以让它适用于关联数组。

关于bash 4.x assoc 数组在接收函数中丢失键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23304478/

相关文章:

bash - 在 bash 中将多行输出捕获为数组

bash - 重新排列文件中的数据(不是直接转置)

shell - .Sh脚本在特定位置安装java

c - 跟踪结果是否已经使用哈希表计算

linux - 比较日志中的纪元时间戳并检查列表中的前一个时间戳和当前时间戳之间是否经过了 x 时间

bash - 如果另一个程序返回错误则自动运行一个程序

c# - 如何在 C# 中编写 Powershell Wrapper?

shell - Jenkins 将 shell 输出保存到 var

java - 什么是 Python 字典的 Java 等价物

actionscript-3 - ActionScript 3 Dictionary 是 HashMap 吗?