SHELL脚本--shell数组基础
数组和变量的区别是:变量在内存中占用的空间是离散的,数组在内存中是先开辟一段连续的大内存空间,随后数组中的每个元素都放入数组内存中。数组元素使用数组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