1. 数组简介
- 变量:存储单个元素的内存空间
- 数组:存储多个元素的连续的内存空间,相当于多个变量的集合
- 数组名和索引
索引:编号从0开始,属于数值索引- 注意:索引可支持使用自定义的格式,而不仅是数值格式,即为关联索引,从bash4.0版本之后开始支持
2. 声明数组:
数组的作用范围
数组其实也是属于变量,只不过是变量的合集;因子数组也分为环境数组,普通数组以及局部数组
声明普通数组
declare -a ARRAY_NAME(普通数组):可以不用先声明,直接使用即可
declare -A ARRAY_NAME(关联数组):必须先声明才可以使用,如果先使用了(相当于是一个普通数组),必须unset之后再重新声明为关联数组才可以使用
- 注意:两者不可相互转换,下同
声明环境数组
declare -xa ARRAY_NAME(普通数组):可以不用先声明,直接使用即可
declare -xA ARRAY_NAME(关联数组):必须先声明才可以使用,如果先使用了(相当于是一个普通数组),必须unset之后再重新声明为关联数组才可以使用
声明局部数组(只能在函数中使用)
local [-a] ARRAY_NAME(普通数组):可以不用先声明,直接使用即可
local -A ARRAY_NAME(关联数组):必须先声明才可以使用,如果先使用了(相当于是一个普通数组),必须unset之后再重新声明为关联数组才可以使用
3. 数组注意点:
- bash的数组支持稀疏格式(索引不连续),非常实用,但是要注意稀疏格式的数组总个数就是有元素的个数,而不是数组的下标的最大值的个数
- 注意单个字符串(也就是变量名)取其中字符串长度的时候不需要加下标
${#varialble}(也可以加上下标为0,也就是{#varialble[0]}),同时字符串想要取中间的部分字符,只能用${var:#:#}的这种方式,因为var它就相当于数组只有一个元素它本身(或者说这个字符串开头的地址var[0])- 单个字符串(也就是变量)如果
${#varialble[*]}则结果是1,因为它可以看做是一个只有一个元素的数组,其中的元素就是这个字符串。 - 只有包含多个元素(字符串)的数组,取其中一个元素(字符串)长度的时候才加下标
${#array[下标数]}。
- 单个字符串(也就是变量)如果
- 而数组中的每个元素中内容想要切片的话则要加上下标
${array[INDEX]:#:#},(此时就是把这个带下标的数组元素名当做一个地址,看作是本身的下标0了)。取数组中的各个元素的话则是${array[*|@]:#:#}的方式。 - 不写下标默认其为0
- 因此字符串(也就是变量),当不写下标的时候就是代表整个字符串
- 而数组中如果不写下标就是代表这个数组里面的第一个元素。
# abc=12334
# echo ${abc[0]}
12334
# echo ${abc}
12334
# echo ${#abc}
5
# array=([1]=12wad [5]=ff [6]=cvv [8]=1wd234)
# echo $array
# echo ${array[0]}
# echo ${array[1]}
12wad
# echo ${#array[1]} :第一个元素的长度
5
# echo ${#array[*]} :数组总长度,稀疏数组只看有几个元素就是几
4
# echo ${array[1]:2:3} :第一个元素内容切片
wad
# echo ${array[*]}
12wad ff cvv 1wd234
# echo ${array[*]:2:2} :取不同的数组元素,注意和元素内容切片的区分
ff cvv
# echo ${array[*]:2:3}
ff cvv 1wd234
4. 数组赋值
4.1. 数组元素的赋值
- 一次只赋值一个元素ARRAY_NAME[INDEX]=VALUE weekdays[0]="Sunday" weekdays[4]="Thursday"
- 一次赋值全部元素(注意尽量要加上引号,虽然空格也可以作为分隔符)ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)
- 只赋值特定元素ARRAY_NAME=([0]="VAL1" [3]="VAL2" ...)
- 交互式数组值对赋值(注意有一个-a的选项)read -a ARRAY
- 显示所有数组:declare -a
4.2. 特殊的赋值方式:
num=({1..10}) :1到10赋值给num[0]到num[9]
file=(*.sh) :当前目录中sh后缀的文件名赋值给file数组
4.3. 稀疏方式赋值注意点:
如果先一个一个赋值,然后又一次赋值特定元素(3中的方式),就算赋值的元素下标并不一样,但这样仍然则会将一个一个赋值的结果给覆盖掉(没赋值到的元素则为空,其实这也就是相当于全覆盖了整个数组,相当于之前一个一个赋值的所有内容全部被清除了,3中方式赋值后整个数组就是个新的数组了)
但是反过来如果先一次性赋值(3中的方式),然后再一个一个赋值下标不同的数组元素,则不会覆盖掉一次性赋值的元素
4.3.1. 比如说:
19:40[root@centos7 /data]# testarray[2]=12
19:40[root@centos7 /data]# testarray[5]=1234
19:40[root@centos7 /data]# echo ${testarray[2]}
12
19:40[root@centos7 /data]# declare -a
declare -a testarray='( [2]="12" [5]="1234")'
19:40[root@centos7 /data]# testarray=( [1]=wade [3]=waef )
19:40[root@centos7 /data]# echo ${testarray[2]}
19:40[root@centos7 /data]# declare -a
declare -a testarray='([1]="wade" [3]="waef")'
上面会覆盖,然后继续,下面的不会覆盖:
19:40[root@centos7 /data]# testarray[2]=12
19:44[root@centos7 /data]# testarray[5]=1234
19:44[root@centos7 /data]# declare -a
declare -a testarray='([1]="wade" [2]="12" [3]="waef" [5]="1234")'
5. 数组数据处理
5.1. 引用数组
引用数组元素
- 注意:省略[INDEX]表示引用下标为0的元素
${ARRAY_NAME[INDEX]}引用数组所有元素
${ARRAY_NAME[*]} ${ARRAY_NAME[@]}数组的长度(数组中元素的个数)
${#ARRAY_NAME[*]} ${#ARRAY_NAME[@]}删除数组中的某元素:导致稀疏格式
unset ARRAY[INDEX]删除整个数组
- 类似的还有删除变量,删除函数,注意都是从内存中删除掉
unset ARRAY
5.2. 引用数组中的元素:
- 数组切片:${ARRAY[*]:offset:number} offset 要跳过的元素个数 number 要取出的元素个数
- 取偏移量之后的所有元素${ARRAY[*]:offset}
- 向数组中追加元素(因为下标从0开始):ARRAY[${#ARRAY[*]}]=value
- 关联数组:
- 注意:关联数组必须先声明再调用
declare -A ARRAY_NAME ARRAY_NAME=([idx_name1]='val1' [idx_name2]='val2'...)
5.3. 示例
- 生成10个随机数保存于数组中,并找出其最大值和最小值
- (优化算法:不要每次都判断是否是第一个,把第一个赋值写在for循环外面,然后for循环直接从1开始即可)
#!/bin/bash
declare -i min max
declare -a nums
for ((i=0;i<10;i++));do
nums[$i]=$RANDOM
[ $i -eq 0 ] && min=${nums[$i]} && max=${nums[$i]} && continue
[ ${nums[$i]} -gt $max ] && max=${nums[$i]}
[ ${nums[$i]} -lt $min ] && min=${nums[$i]}
done
echo “All numbers are ${nums[*]}”
echo Max is $max
echo Min is $min
编写脚本,定义一个数组,数组中的元素对应的值是
/var/log目录下所有以.log结尾的文件;统计出其下标为偶数的文件中的行数之和
#!/bin/bash
#
declare -a files
files=(/var/log/*.log)
declare -i lines=0
for i in $(seq 0 $[${#files[*]}-1]); do
if [ $[$i%2] -eq 0 ];then
let lines+=$(wc -l ${files[$i]} | cut -d' ' -f1)
fi
done
echo "Lines: $lines."
6. 字符串处理
6.1. 字符串切片
${#var}- 返回字符串变量var的长度
${var:offset}- 返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,到最后的部分,offset的取值在0 到
${#var}-1之间 (bash4.2后,允许为负值)
- 返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,到最后的部分,offset的取值在0 到
${var:offset:number}- 返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,长度为number的部分
${var: -length}- 取字符串的最右侧几个字符
- 注意:冒号后必须有一空白字符
- 取字符串的最右侧几个字符
${var:offset:-length}- 从最左侧跳过offset字符,一直向右取到距离最右侧lengh个字符之前的内容
${var: -length:-offset}- 先从最右侧向左取到length个字符开始,再向右取到距离最右侧offset个字符之间的内容
- 注意:-length前有空格(中间的那个必须有空格,:最后的一项可以不加空格)
- 先从最右侧向左取到length个字符开始,再向右取到距离最右侧offset个字符之间的内容
6.2. 引用字符串
${var#*word}:其中word可以是指定的任意字符- 功能:自左而右,查找var变量所存储的字符串中,第一次出现的word, 删除字符串开头至第一次出现word字符串(含)之间的所有字符
${var##*word}:同上,贪婪模式,- 不同的是,删除的是字符串开头至最后一次由word指定的字符之间的所有内容
- 示例:
file=“var/log/messages” ${file#*/}: log/messages ${file##*/}: messages${var%word*}:其中word可以是指定的任意字符- 功能:自右而左,查找var变量所存储的字符串中,第一次出现的word, 删除字符串最后一个字符向左至第一次出现word字符串(含)之间的所有字符
- 例子:
file="/var/log/messages" ${file%/*}: /var/log${var%%word*}:- 同上,只不过删除字符串最右侧的字符向左至最后一次出现word字符之间的所有字符
- 示例:
url=http://www.baidu.com:80 ${url##*:} 80 ${url%%:*} http
6.3. 字符串查找替换
${var/pattern/substr}- 查找var所表示的字符串中,第一次被pattern所匹配到的字符串,以substr替换之
${var//pattern/substr}- 查找var所表示的字符串中,所有能被pattern所匹配到的字符串,以substr替换之
${var/#pattern/substr}- 查找var所表示的字符串中,行首被pattern所匹配到的字符串,以substr替换之
${var/%pattern/substr}- 查找var所表示的字符串中,行尾被pattern所匹配到的字符串,以substr替换之
6.4. 字符串查找并删除
${var/pattern}- 删除var表示的字符串中第一次被pattern匹配到的字符串,从左往右匹配
${var//pattern}- 删除var表示的字符串中所有被pattern匹配到的字符串,从左往右匹配
${var/#pattern}- 删除var表示的字符串中所有以pattern为行首匹配到的字符串
${var/%pattern}- 删除var所表示的字符串中所有以pattern为行尾所匹配到的字符串
6.5. 字符大小写转换
${var^^}- 把var中的所有小写字母转换为大写
${var,,}- 把var中的所有大写字母转换为小写
6.6. 变量赋值的其他形式

- 注意里面的expr是一个字符串,不是一个变量。直接就是双引号引起来的字符串。
留言