#4: 使用数组

到目前为止,你已经可以在bash脚本中使用有限数量的变量,你可以创建一些变量来保存一两个文件名或者用户名。

但是,如果bash脚本的变量不止七八个,而是几十甚至上百个呢?难道就傻傻的在脚本里面写100遍?

其实你可以不用这么做,因为数组提供了更好的解决方案。

创建第一个数组

假设你想一个名为timestamp.sh的脚本用于更新五个不同文件的时间戳

根据之前学习到的知识,我们需要把这五个文件都指定,然后再去更新他们的时间戳:

#!/bin/bash

file1="f1.txt"
file2="f2.txt"
file3="f3.txt"
file4="f4.txt"
file5="f5.txt"

touch $file1
touch $file2
touch $file3
touch $file4
touch $file5

现在,不再使用五个变量来存储五个文件名的值,而是通过创建一个数组来保存所有文件名,下面是在bash里面数组的语法:

array_name=(value1 value2 value3 … )

所以现在你可以创建一个名为files的数组来存储你在timestamp.sh脚本中使用的五个文件的文件名,如下所示:

files=("f1.txt" "f2.txt" "f3.txt" "f4.txt" "f5.txt")

就是这么简单,仅仅用一个数组替换了五个变量,更简洁和高效的shell代码就写好了。

访问数组中的元素

数组中的第一个元素从索引0开始,因此要访问数组中的第n个元素时,需要使用n -1索引。

例如,要打印文件数组中第二个元素的值,可以使用下面的echo语句:

echo ${files[1]}

要打印文件数组的第三个元素的值,你可以这样写:

echo ${files[2]}

以此类推。

下面的脚本reverse.sh将以相反的顺序打印出文件数组中的五个值,它从最后一个数组开始打印。

#!/bin/bash

files=("f1.txt" "f2.txt" "f3.txt" "f4.txt" "f5.txt")

echo ${files[4]}
echo ${files[3]}
echo ${files[2]}
echo ${files[1]}
echo ${files[0]}

打印数组

看,这里写了好多个echo语句啊,使用过其他语言的朋友肯定会问,为什么不用循环语句?难道bash没有循环语句吗?bash肯定是有循环语句的,只是现在还没有讲到而已。

也可以用下面的语法一次打印出所有的数组元素:

echo ${files[*]}

f1.txt f2.txt f3.txt f4.txt f5.txt

你可以打印文件数组元素的总所,也就是数组的大小(长度):

echo ${#files[@]}

5

你也可以更新数组中任何元素的值;例如:可以用以下复制将files数组的第一个元素的值更改为“a.txt”:

files[0]="a.txt"

添加数组元素

让我们创建一个里面包含了流行的Linux发行版本名称的数组:

distros=("Ubuntu" "Red Hat" "Fedora")

distros数组中包含三个元素。你可以通过+=操作符将新的元素添加(追加)到数组的末尾。

如下所示,你可以将Kali添加到distros数组中:

distros+=("Kali")

现在distros数组就包含了四个元素,Kali是最后一个元素。

数组添加元素

删除数组元素

Let’s first create a num array that will store the numbers from 1 to 5:

首先创建一个数组,里面存储1到5五个整数:

num=(1 2 3 4 5)

You can print all the values in the num array:

可以打印看一下里面全部的值:

echo ${num[*]}

1 2 3 4 5

You can delete the 3rdelement of the num array by using the unset shell built-in:

你可以使用unset来删除掉第三个元素,如下所示:

unset num[2]

Now, if you print all the values of the num array:

现在你在打印出数组的全部值

echo ${num[*]}
1 2 4 5

As you can see, the third element of the array num has been deleted.

可以看到,第三个元素的值已经被删除了。

You can also delete the whole num array in the same way:

你可以用同样的方法来删掉整个数组里面的值:

unset num

数组删除元素

创建具有不同数据类型的混合数组

bash不像其他变成语言,你可以创建一个容纳不同数据类型的数组,看看下面的user.sh脚本:

#!/bin/bash

user=("john" 122 "sudo,developers" "bash")

echo "User Name: ${user[0]}"
echo "User ID: ${user[1]}"
echo "User Groups: ${user[2]}"
echo "User Shell: ${user[3]}"

注意看user数组中的四个元素:

  1. "John" ----> 字符串类型
  2. 122 ---> 整数类型
  3. "sudo,developers" ---> 字符串类型
  4. "bash" ---> 字符串类型

So, it’s totally ok to store different data types in the same array. Isn't that awesome?

所以,在同一个数字里面存储不同的数据类型是完全可行的,是不是很神奇?

数组数据类型混合

练习题

自己动手做练习可以帮助你记忆刚学到的东西,下面是几到简单的练习题,用到了上面提到的内容。如果您是初学者,建议您可以自己动手做一下。

练习 1:彩虹的颜色

写一个shell脚本,用一个数组存储彩虹的七种颜色并将其打印出来。

难度级别:容易

提示:一个数组存储彩虹的七种颜色:红、橙、黄、绿、青、蓝、紫。

练习 2:选一种颜色

写一个shell脚本,选出练习1中的一种颜色。

难度级别:容易

提示:打印数组中与所需颜色相对应的特定元素

练习 3:彩虹有多少种颜色?

编写一个shell脚本,打印出练习1中的彩虹的颜色数量。

难度级别:容易

提示:用echo ${#rainbow[@]}命令其中的 rainbow 就是彩虹数组的名字。

练习 4:交换颜色

编写shell脚本,把练习1中的彩虹数组交换任意两种颜色的位置。

难度级别:中等

提示:使用一个临时变量来存储任意两个元素然后然后交换这两个元素的位置。

练习 5:添加一个新颜色到彩虹数组

写一个脚本,输入一个命令作为参数输出该命令的二进制文件路径。

难度级别:容易

提示:用命令rainbow+=("cyan")来增加一个新的颜色。

练习题答案

答案 1:这个脚本叫什么名字?

写一个shell脚本,用一个数组存储彩虹的七种颜色并将其打印出来。

#! /bin/bash
rainbow=("violet" "indigo" "blue" "green" "yellow" "orange" "red")
echo "Colors of the rainbow:"
echo ${rainbow[*]}

答案 2:选一种颜色

写一个shell脚本,选出练习1中的一种颜色。

#!/bin/bash
rainbow=("violet" "indigo" "blue" "green" "yellow" "orange" "red")
echo "Colors of the rainbow:"
echo ${rainbow[*]}
echo "First color on this rainbow array:"
echo ${rainbow[0]}

答案 3:彩虹有多少种颜色?

编写一个shell脚本,打印出练习1中的彩虹的颜色数量。

#!/bin/bash
rainbow=("violet" "indigo" "blue" "green" "yellow" "orange" "red")
echo "Colors of the rainbow:"
echo ${rainbow[*]}
echo "Number of colors of this rainbow:"
echo ${#rainbow[@]}

答案 4:交换颜色

编写shell脚本,把练习1中的彩虹数组交换任意两种颜色的位置。

这个例子我选择索引0的violet,和索引4的yellow进行交换

#!/bin/bash
rainbow=("violet" "indigo" "blue" "green" "yellow" "orange" "red")
echo "Colors of the rainbow:"
echo ${rainbow[*]}
echo "Before swapping positions 0 and 4, the colors are arranged as:"
echo ${rainbow[*]}
temp=${rainbow[4]}
rainbow[4]=${rainbow[0]}
rainbow[0]=$temp
echo "After swapping positions 0 and 4, the colors are rearranged as:"
echo ${rainbow[*]}

答案 5:添加一个新颜色到彩虹数组

写一个脚本,输入一个命令作为参数输出该命令的二进制文件路径。

#!/bin/bash
rainbow=("violet" "indigo" "blue" "green" "yellow" "orange" "red")
echo "Colors of the rainbow:"
echo ${rainbow[*]}
rainbow+=("cyan")
echo "Adding an eighth color "cyan" to this rainbow..coz why not?"
sleep 2
echo "New rainbow:"
echo ${rainbow[*]}