Warm tip: This article is reproduced from serverfault.com, please click

dictionary-如何在 Bash 中定义哈希表?

(dictionary - How to define hash tables in Bash?)

发布于 2009-09-29 18:29:38

什么是Python 字典的等价物,但在 Bash 中(应该在 OS X 和 Linux 上工作)。

Questioner
Sridhar Ratnakumar
Viewed
22
35.8k 2021-11-04 05:14:42

Bash 4

Bash 4 本身就支持这个特性。确保你的脚本hashbang是#!/usr/bin/env bash或者#!/bin/bash让你不使用结束sh确保你是直接执行脚本,或者script使用bash script. (实际上并没有使用 Bash 执行 Bash 脚本确实会发生,而且会非常混乱!)

你可以通过执行以下操作来声明关联数组:

declare -A animals

你可以使用普通的数组赋值运算符用元素填充它。例如,如果你想要一张 mapanimal[sound(key)] = animal(value)

animals=( ["moo"]="cow" ["woof"]="dog")

或者在一行中声明和实例化:

declare -A animals=( ["moo"]="cow" ["woof"]="dog")

然后像普通数组一样使用它们。

  • animals['key']='value' 设定值

  • "${animals[@]}" 扩大价值

  • "${!animals[@]}"(注意!) 展开键

不要忘记引用它们:

echo "${animals[moo]}"
for sound in "${!animals[@]}"; do echo "$sound - ${animals[$sound]}"; done

Bash 3

在 bash 4 之前,你没有关联数组。 不要eval用来模仿它们避免eval像瘟疫一样,因为它shell 脚本的瘟疫。最重要的原因是eval将你的数据视为可执行代码(还有许多其他原因)。

首先也是最重要的:考虑升级到 bash 4。这将使整个过程对你来说更容易。

如果有不能升级的原因,这declare是一个更安全的选择。它不像 bash 代码那样评估数据,eval因此不允许任意代码注入很容易。

让我们通过引入概念来准备答案:

第一,间接。

$ animals_moo=cow; sound=moo; i="animals_$sound"; echo "${!i}"
cow

其次,declare

$ sound=moo; animal=cow; declare "animals_$sound=$animal"; echo "$animals_moo"
cow

把它们放在一起:

# Set a value:
declare "array_$index=$value"

# Get a value:
arrayGet() { 
    local array=$1 index=$2
    local i="${array}_$index"
    printf '%s' "${!i}"
}

让我们使用它:

$ sound=moo
$ animal=cow
$ declare "animals_$sound=$animal"
$ arrayGet animals "$sound"
cow

注意:declare不能放在函数中。declare在 bash 函数内部的任何使用都会将它创建的变量变为该函数范围内的局部变量,这意味着我们无法使用它访问或修改全局数组。(在 bash 4 中,你可以使用declare -g声明全局变量 - 但在 bash 4 中,你可以首先使用关联数组,从而避免这种变通方法。)

概括:

  • 升级到 bash 4 并declare -A用于关联数组。
  • declare如果你无法升级,请使用该选项。
  • 考虑awk改用并完全避免这个问题。