27. 数组

新版本的Bash支持一维数组。 数组元素可以使用符号variable[xx] 来初始化。另外,脚本可以使用declare -a variable语句来指定一个数组。 如果想引用一个数组元素(也就是取值),可以使用大括号,访问形式为 ${element[xx]} 。

例子 27-1. 简单的数组使用

#!/bin/bash

area[11]=23
area[13]=37
area[51]=UFOs

#  数组成员不一定非得是相邻或连续的。

#  数组的部分成员可以不被初始化。
#  数组中允许空缺元素。
#  实际上,保存着稀疏数据的数组(“稀疏数组”) 
#+ 在电子表格处理软件中是非常有用的。

echo -n "area[11] = "
echo ${area[11]}    #  需要{大括号}。

echo -n "area[13] = "
echo ${area[13]}

echo "Contents of area[51] are ${area[51]}."

# 没被初始化的数组成员打印为空值(null变量)。
echo -n "area[43] = "
echo ${area[43]}
echo "(area[43] unassigned)"

echo

# 两个数组元素的和被赋值给另一个数组元素。
area[5]=`expr ${area[11]} + ${area[13]}`
echo "area[5] = area[11] + area[13]"
echo -n "area[5] = "
echo ${area[5]}

area[6]=`expr ${area[11]} + ${area[51]}`
echo "area[6] = area[11] + area[51]"
echo -n "area[6] = "
echo ${area[6]}
# 这里会失败,是因为不允许整数与字符串相加。

echo; echo; echo

# -----------------------------------------------------------------
# 另一个数组, "area2".

# 另一种给数组变量赋值的方法...
# array_name=( XXX YYY ZZZ ... )

area2=( zero one two three four )

echo -n "area2[0] = "
echo ${area2[0]}
# 啊哈,从0开始计算数组下标(也就是,数组的第一个元素为[0],而不是[1]).

echo -n "area2[1] = "
echo ${area2[1]}    # [1] 是数组的第二个元素。
# -----------------------------------------------------------------

echo; echo; echo

# -----------------------------------------------
# 第三个数组, "area3".
# 另外一种给数组元素赋值的方法...
# array_name=([xx]=XXX [yy]=YYY ...)

area3=([17]=seventeen [24]=twenty-four)

echo -n "area3[17] = "
echo ${area3[17]}

echo -n "area3[24] = "
echo ${area3[24]}
# -----------------------------------------------

exit 0

我们可以看出,初始化整数的一个简单的方法是 array=( element1 element2 ... elementN ) 。

Bash 允许把变量当成数据来操作,即使这个变量没有明确地被声明为数组。

类似的示范可以参考 Bash变量是无类型的

例子 27-2. 格式化一首诗

数组元素有它们独特的语法,甚至标准Bash命令和操作符,都有特殊的选项用以配合数组操作。

例子 27-3. 多种数组操作

大部分标准字符串操作 都可以用于数组中。

例子27-4. 用于数组的字符串操作

命令替换 可以构造数组的独立元素。

例子 27-5. 将脚本中的内容赋值给数组

在数组环境中,某些Bash 内建命令 的含义可能会有些轻微的改变。比如,unset 命令可以删除数组元素,甚至能够删除整个数组。

例子 27-6. 一些数组的专有特性

正如我们在前面的例子中所看到的,${array_name[@]} 或者 ${array_name[*]} 都与数组中的所有元素相关。同样的,为了计算数组的元素个数,可以使用 ${array_name[@]} 或者 ${array_name[*]}${#array_name} 是数组第一个元素的长度,也就是 ${array_name[0]} 的长度(字符个数)。

例子 27-7. 空数组与包含空元素的数组

${array_name[@]}${array_name[*]} 的关系非常类似于 $@ 和$*。这种数组用法非常广泛。

info array=( element1 element2 ... elementN ) 初始化操作,如果有命令替换的帮助,就可以将一个文本文件的内容加载到数组。

出色的技巧使得数组的操作技术又多了一种。

例子 27-8. 初始化数组

extra 在数组声明的时候添加一个额外的declare -a语句,能够加速后续的数组操作速度。

例子 27-9. 拷贝和连接数组

例子27-10. 关于串联数组的更多信息


有了数组, 我们就可以在脚本中实现一些比较熟悉的算法. 这么做, 到底是不是一个好主意, 我们在这里不做讨论, 还是留给读者决定吧.

例子 27-11. 冒泡排序


我们可以在数组中嵌套数组么?


如果将“嵌套数组”与间接引用 组合起来使用的话,将会产生一些非常有趣的用法。

例子 27-12. 嵌套数组与间接引用


数组使得埃拉托色尼素数筛子有了shell版本的实现. 当然, 如果你需要的是追求效率的应用, 那么就 应该使用编译行语言来实现, 比如C语言. 因为脚本运行的太慢了.

例子 27-13. 埃拉托色尼素数筛子

例子 27-14. 埃拉托色尼素数筛子,优化版

上边的这个例子是基于数组的素数产生器, 还有不使用数组的素数产生器例子A-15例子 16-46,让我们来比较一番.


数组可以进行一定程度上的扩展, 这样就可以模拟一些Bash原本不支持的数据结构.

例子 27-15. 模拟一个压入栈


如果想对数组"下标"做一些比较诡异的操作, 可能需要使用中间变量. 对于那些有这种需求的项目来说, 还是应该考虑使用功能更加强大的编程语言, 比如Perl或C。

例子 27-16. 复杂的数组应用: 探索一个神秘的数学序列


Bash仅仅支持一维数组, 但是我们可以使用一个小手段, 这样就可以模拟多维数组了.

例子 27-17. 模拟一个二维数组,并使它倾斜

二维数组本质上其实就是一个一维数组, 只不过是添加了行和列的寻址方式, 来引用和操作数组的元素而已.

这里有一个精心制作的模拟二维数组的例子, 请参考例子 A-10.


还有更多使用数组的有趣的脚本,请参考:

最后更新于

这有帮助吗?