SHELL脚本--shell数组基础

onetozero 2019-12-06

数组和变量的区别是:变量在内存中占用的空间是离散的,数组在内存中是先开辟一段连续的大内存空间,随后数组中的每个元素都放入数组内存中。数组元素使用数组index标识。

bash里有两种数组:普通数组和关联数组。普通数组只能使用整型数值作为数组索引,关联数组可以使用字符串作为索引。所谓的关联数组,它的另外三种称呼:字典(dict)、hash结构和映射(map),是一种key和value一 一对应的关系。

普通数组                            

 定义数组的方式一:     

[ ~]#  array_test=(1 2 3 4)

它们分别存储在索引位0-3的位置上,是array_test[0]到array_test[3]对应的值。此时array_test[0]表示的是一个变量,所以使用$来引用。数组的引用方式:${array_name[index]}。

[ ~]# echo ${array_test[2]}
3

注意数组中定义是使用空格作为分隔符定义在括号内,而不是逗号。如果使用逗号,则它们将作为一个整体,也就是数组索引0的值。如果使用逗号,则:

[ ~]# array_test=(1,2,3,4) 
[ ~]# echo ${array_test[0]}
1,2,3,4

定义数组的方式二:可以自定义索引位。

[ ~]# array_test1[1]=1
[ ~]# array_test1[2]=2
[ ~]# array_test1[3]=3
[ ~]# array_test1[4]=4
[ ~]# echo ${array_test1[*]}
1 2 3 4

但是在索引位4之后定义array_test1[7]=7则表示5和6的数组变量未定义,即不存在,这可以通过统计变量的元素个数来验证。但在shell中是可以直接引用未定义变量的,只不过它们的初始值是空或是0。

(1).打印数组所有值。

[ ~]# echo ${array_test1[*]}
1 2 3 4

或者使用@符号。

[ ~]# echo ${array_test1[@]}
1 2 3 4

(2).查看数组索引号。

[ ~]# echo ${!array_test1[*]}
1 2 3 4
[ ~]# echo ${!array_test1[@]}
1 2 3 4

(3).数组中变量长度和数组长度。

[ ~]# echo ${#array_test1[1]}  # 显示下标为1的数组变量的字符长度
1
[ ~]# echo ${#array_test1[*]}  # 显示数组中的元素个数(只统计值不为空的元素)
4
[ ~]# echo ${#array_test1[@]}  # 显示数组中的元素个数(只统计值不为空的元素)
4

关联数组                            

关联数组支持字符串作为数组索引。使用关联数组必须先使用declare -A声明它。

[ ~]# declare -A array_dep
[ ~]# array_dep=([name1]=longshuai [name2]=xiaofang)

其中name1和name2就是关联数组的index。引用数组变量时需要使用index来引用对应的值。

[ ~]# echo ${array_dep[name1]}
longshuai

也可以分开赋值。

[ ~]# array_dep[name3]=zhangsan
[ ~]#  array_dep[name4]=lisi
[ ~]# echo ${array_dep[name4]}
lisi

(1).查看数组所有值。

[ ~]# echo ${array_dep[@]}
zhangsan xiaofang longshuai lisi
[ ~]# echo ${array_dep[*]}
zhangsan xiaofang longshuai lisi

(2).查看数组索引号。

[ ~]# echo ${!array_dep[@]}
name3 name2 name1 name4
[ ~]# echo ${!array_dep[*]}
name3 name2 name1 name4

(3).统计数组长度。

[ ~]#  echo ${#array_dep[*]}
4
[ ~]#  echo ${#array_dep[@]}
4

数组元素截取、替换                        

和变量的截取和替换是类似的。

[ ~]# array=(1 2 3 4 5 6)
[ ~]# array0=${array[*]:2:2} # 从数组全部元素中第2个元素向后截取2个元素出来(即3 4)
[ ~]# array1=${array[*]/5/6}  # 将数组中的5替换称6

还有从左匹配删除从右匹配删除,和变量是一样的。

[ ~]# array=(one two three foue five)
[ ~]# array1=${array[*]#*o}  # 从左非贪婪匹配并删除所有数组变量中匹配内容
[ ~]# array2=${array[*]##*o}  # 从左贪婪匹配并删除所有数组变量中匹配的内容
[ ~]# array2=${array[*]%o}  # 从右非贪婪匹配并删除所有数组变量中匹配内容
[ ~]# array2=${array[*]%%o}   # 从右贪婪匹配并删除所有数组变量中匹配内容

for循环遍历数组                          

在shell中的循环结构中,可以使用数组名来表示整个数组变量。

[ ~]# for i in ${array[*]};do   echo $i; done
one
two
three
foue
five

或者让i变成数组index的方法:

[ ~]# for i in ${!array[*]};do
> echo $i
> done
0
1
2
3
4

以下是遍历数组的三个常见用法总结:

array=($(ls /boot))

for i in ${array[*]};do  # 以数组值的方式直接遍历数组
    echo $i
done

for ((i=0;i<${#array[*]};i++));do    # 以数组变量个数的方式遍历数组
    echo ${array[$i]}
done

for i in ${!array[*]};do      # 以数组index的方式遍历数组
    echo ${array[$i]}
done

以下是一个数组遍历的示例:统计文件中重复行的次数。假设a.log文件中内容如下。

[ ~]# vi a.log
portmapper
portmapper
portmapper
portmapper
portmapper
portmapper
status
status
mountd
mountd
mountd
mountd
mountd
mountd
nfs
nfs
nfs_acl
nfs
nfs
nfs_acl
nlockmgr
nlockmgr
nlockmgr
nlockmgr
nlockmgr
nlockmgr

以下是数组遍历的脚本。

[ ~]# vi shuzu.sh
#!/bin/bash

declare -A array_test  # 定义关联数组

for i in `cat ~/a.log`
do
    let ++array_test[$i]
done

for j in ${!array_test[*]}
do
    printf "%-15s %3s\n" $j :${array_test[$j]}
done

该脚本中第一个for循环中,以文件中内容做数组的index,每遍历到一个index就对该index进行数学运算的自加1操作。这一过程是遍历文件内容并为数组变量赋值的过程。

这样就得到如下结果:

array_test[status]=2
array_test[nfs]=4
array_test[portmapper]=6
array_test[nlockmgr]=6
array_test[nfs_acl]=2
array_test[mountd]=6

第二个for循环是将array_test数组中所有数组变量及其值取出来,这一步是遍历数组的过程。所以得到最终的结果:

[ ~]# bash shuzu.sh 
status           :2
nfs              :4
portmapper       :6
nlockmgr         :6
nfs_acl          :2
mountd           :6

相关推荐