什么是Python 字典的等价物,但在 Bash 中(应该在 OS X 和 Linux 上工作)。
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 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 中,你可以首先使用关联数组,从而避免这种变通方法。)
概括:
declare -A
用于关联数组。declare
如果你无法升级,请使用该选项。awk
改用并完全避免这个问题。
无法升级:我在 Bash 中编写脚本的唯一原因是为了“随处运行”的可移植性。因此,依靠 Bash 的一个非通用特性排除了这种方法。这是一种耻辱,因为否则它对我来说将是一个很好的解决方案!
遗憾的是 OSX 仍然默认使用 Bash 3,因为这代表了很多人的“默认”。我认为 ShellShock 的恐慌可能是他们需要的推动力,但显然不是。
@ken 这是一个许可问题。OSX 上的 Bash 停留在最新的非 GPLv3 许可版本。
@jww Apple 不会将 GNU bash 升级到 3 以上,因为它对 GPLv3 怀有恶意。但这不应该是一种威慑。
brew install bash
酿造.sh...或者
sudo port install bash
,对于那些(明智地,恕我直言)不愿意在 PATH 中为所有用户创建可写目录而没有明确的每个进程权限提升的人。