43

在 Bash 脚本中将数组分配给变量似乎相当复杂:

a=("a" "b" "c")
b=$a

echo ${a[0]} 
echo ${a[1]}

echo ${b[0]} 
echo ${b[1]} 

导致

a 
b 
a
   

代替

a
b
a
b

为什么?我该如何解决?

4

2 回答 2

69

如果要将包含数组的变量复制到另一个名称,请执行以下操作:

a=('a' 'b' 'c')
b=( "${a[@]}" )
于 2012-09-06T16:01:17.050 回答
24

为什么?

如果a是一个数组,则$a展开到数组中的第一个元素。这就是为什么b在您的示例中只有一个值。在 bash 中,引用数组的变量不能像 C++ 或 Java 中的指针那样赋值。相反,变量扩展(如在参数扩展中)为字符串,这些字符串被复制并与被分配的变量相关联。

我该如何解决?

要复制包含带空格的值的稀疏数组,必须通过索引一次复制一个元素 - 可以使用 ${!a[@]} 获得。

declare -a b=()
for i in ${!a[@]}; do
    b[$i]="${a[$i]}"
done

从 bash 手册页:

可以获得数组的键(索引)以及值。${!name[@]} 和 ${!name[*]} 扩展为数组变量名中分配的索引。双引号中的处理类似于特殊参数@和*在双引号中的扩展。

这是一个您可以自己测试的脚本:

#!/bin/bash

declare -a a=();
a[1]='red hat'
a[3]='fedora core'

declare -a b=();

# Copy method that works for sparse arrays with spaces in the values.
for i in ${!a[@]}; do
    b[$i]="${a[$i]}"
done

# does not work, but as LeVar Burton says ...
#b=("${a[@]}")

echo a indicies: ${!a[@]}
echo b indicies: ${!b[@]}

echo "values in b:"
for u in "${b[@]}"; do
    echo $u
done

印刷:

a indicies: 1 3
b indicies: 1 3  # or 0 1 with line uncommented
values in b:
red hat
fedora core

这也适用于 bash 4 中的关联数组,如果您declare -A在声明数组时使用(使用大写 A 而不是小写)。

于 2014-08-07T05:22:51.147 回答