<h2>猛击4</h2>
<p>Bash 4本机支持这个特性。确保脚本的hashbang是<code>#!/usr/bin/env bash</code>或<code>#!/bin/bash</code>,这样就不会使用<code>sh</code>。确保直接执行脚本,或者使用<code>bash script</code>执行<code>script</code>。(使用Bash<em>不实际执行Bash脚本确实会发生</em>的情况,而且会让<em>感到困惑!)</p>
<p>通过执行以下操作声明关联数组:</p>
<pre><code>declare -A animals
</code></pre>
<p>可以使用普通数组赋值运算符将其填充为元素。例如,如果要有<code>animal[sound(key)] = animal(value)</code>的映射:</p>
<pre><code>animals=( ["moo"]="cow" ["woof"]="dog")
</code></pre>
<p>或者合并它们:</p>
<pre><code>declare -A animals=( ["moo"]="cow" ["woof"]="dog")
</code></pre>
<p>然后像普通数组一样使用它们。使用</p>
<ul>
<li><p><code>animals['key']='value'</code>设置值</p></li>
<li><p><code>"${animals[@]}"</code>展开值</p></li>
<li><p><code>"${!animals[@]}"</code>(注意<code>!</code>)展开键</p></li>
</ul>
<p>别忘了引用它们:</p>
<pre><code>echo "${animals[moo]}"
for sound in "${!animals[@]}"; do echo "$sound - ${animals[$sound]}"; done
</code></pre>
<h2>猛击3</h2>
<p>在bash 4之前,没有关联数组。<strong>不要使用<code>eval</code>来模拟它们。避免像瘟疫一样,因为它是外壳脚本的瘟疫。最重要的原因是<code>eval</code>将数据视为可执行代码(还有许多其他原因)。</p>
<p><em>首先:考虑升级到bash 4。这将使整个过程对你来说容易得多。</p>
<p>如果有原因不能升级,<code>declare</code>是一个更安全的选择。它不像<code>eval</code>那样计算bash代码的数据,因此不允许非常容易地插入任意代码。</p>
<p>让我们通过介绍以下概念来准备答案:</p>
<p>首先,间接。</p>
<pre><code>$ animals_moo=cow; sound=moo; i="animals_$sound"; echo "${!i}"
cow
</code></pre>
<p>其次,<code>declare</code>:</p>
<pre><code>$ sound=moo; animal=cow; declare "animals_$sound=$animal"; echo "$animals_moo"
cow
</code></pre>
<p>把他们聚在一起:</p>
<pre><code># Set a value:
declare "array_$index=$value"
# Get a value:
arrayGet() {
local array=$1 index=$2
local i="${array}_$index"
printf '%s' "${!i}"
}
</code></pre>
<p>让我们使用它:</p>
<pre><code>$ sound=moo
$ animal=cow
$ declare "animals_$sound=$animal"
$ arrayGet animals "$sound"
cow
</code></pre>
<p>注意:<code>declare</code>不能放在函数中。在bash函数中使用<code>declare</code>会将它创建的变量<em>local</em>转到该函数的作用域,这意味着我们不能用它访问或修改全局数组。(在bash 4中,您可以使用declare-g来声明全局变量,但是在bash4中,您可以首先使用关联数组,从而避免这种解决方法。)</p>
<p>总结:</p>
<ul>
<li>升级到bash 4并对关联数组使用<code>declare -A</code>。</li>
<li>如果无法升级,请使用<code>declare</code>选项。</li>
<li>考虑改用<code>awk</code>并完全避免这个问题。</li>
</ul>