shell编程 13 --- shell 数组的应用实践
13.1 shell数组介绍
数组的概念:
简单地说, Shell的数组就是一个元素集合,它把有限个元素(变量或字符内容)用一个名字来命名,然后用编号对它们进行区分。这个名字就称为数组名,用于区分不同内容的编号就称为数组下标。组成数组的各个元素(变量)称为数组的元素,有时也称为下标变量。
有了Shell数组之后,就可以用相同名字来引用一系列变量及变量值了,并通过数字(索引)来识别使用它们。在很多场合中,使用数组可以缩短和简化程序开发。
13.2 shell数组的定义与增删改查
13.2.1 shell数组的定义
Shell数组的定义有多种方法,列举如下。
方法1:用小括号将变量值括起来赋值给数组变量,每个变量值之间要用空格进行分隔。语法如下:
推荐使用
array=(value1 value2 value3 value4 ...)
## 实例:
[root@zabbix 0514]# array=(1 2 3)
[root@zabbix 0514]# echo ${array[*]}
1 2 3
**方法2:用小括号将变量值括起来,同时采用键值对的形式赋值。**语法如下:
此方法比较复杂,不推荐使用
[root@zabbix 0514]# array=([1]=one [2]=two [3]=three)
[root@zabbix 0514]# echo ${array[*]}
one two three
[root@zabbix 0514]# echo ${array[1]}
one
[root@zabbix 0514]# echo ${array[2]}
two
[root@zabbix 0514]# echo ${array[3]}
three
方法3:通过分别定义数组变量的方法来定义。语法如下:
此方法比较复杂,不推荐使用
[root@zabbix 0514]# array[0]=a;array[1]=b;array[2]=c;
[root@zabbix 0514]# echo ${array[*]}
a b c
方法4:动态地定义数组变量,并使用命令的输出结果作为数组的内容。语法为:
array=($(命令)) 或 array=(`命令`)
实例:
[root@zabbix 0514]# mkdir array
[root@zabbix 0514]# touch array/{1..3}.txt
[root@zabbix 0514]# ll array/
total 0
-rw-r--r-- 1 root root 0 May 14 10:06 1.txt
-rw-r--r-- 1 root root 0 May 14 10:06 2.txt
-rw-r--r-- 1 root root 0 May 14 10:06 3.txt
[root@zabbix 0514]# array=($(ls array/))
[root@zabbix 0514]# echo ${array[*]}
1.txt 2.txt 3.txt
13.2.2 Shell数组的打印和输出
13.2.2.1.打印数组元素
[root@zabbix 0514]# array=(one two three four) == 定义数组
[root@zabbix 0514]# echo ${array[1]} == 打印单个元素
two
[root@zabbix 0514]# echo ${array[0]} == 数组下标从0开始
one
[root@zabbix 0514]# echo ${array[*]}
one two three four
[root@zabbix 0514]# echo ${array[@]} == 使用*和@可以得到整个数组元素
one two three four
[root@zabbix 0514]#
13.2.2.2.打印数组元素的个数
# 用${#数组名[*]} 或 ${#数组名[@]} 可以得到数组长度
[root@zabbix 0514]# echo ${array[*]}
one two three four
[root@zabbix 0514]# echo ${#array[*]}
4
[root@zabbix 0514]# echo ${array[@]}
one two three four
[root@zabbix 0514]# echo ${#array[@]}
4
13.2.2.3.数组赋值
可直接通过“数组名[下标]”对数组进行引用赋值,如果下标不存在,则自动添加一个新的数组元素, 如果下标存在,则覆盖原来的值。
[root@zabbix 0514]# array=(one two three four)
[root@zabbix 0514]# echo ${array[@]}
one two three four
[root@zabbix 0514]# echo ${array[0]}
one
[root@zabbix 0514]# array[0]=moox ==> 修改数组元素,覆盖先前元素
[root@zabbix 0514]# echo ${array[0]}
moox
[root@zabbix 0514]# echo ${array[@]}
moox two three four
[root@zabbix 0514]# echo ${array[4]}
[root@zabbix 0514]# array[4]=new ==> 赋值新元素
[root@zabbix 0514]# echo ${array[4]}
new
13.2.2.4.数组的删除
因为数组本质上还是变量,因此可通过“unset数组[下标]”清除相应的数组元素, 如果不带下标,则表示清除整个数组的所有数据。
[root@zabbix 0514]# echo ${array[*]}
moox two three four new
[root@zabbix 0514]# unset array[1]
[root@zabbix 0514]# echo ${array[*]}
moox three four new
[root@zabbix 0514]# unset array
[root@zabbix 0514]# echo ${array[*]}
[root@zabbix 0514]#
13.2.2.5.数组内容的截取、替换和删除
这里和前文变量子串的替换是一样的,因为数组是特殊的变量。 数组元素部分的内容截取的示例如下:
[root@zabbix 0514]# array=(1 2 3 4 5)
[root@zabbix 0514]# echo ${array[@]:1:3}
2 3 4
[root@zabbix 0514]# array=($(echo {a..z}))
[root@zabbix 0514]# echo ${array[@]}
a b c d e f g h i j k l m n o p q r s t u v w x y z
[root@zabbix 0514]# echo ${array[@]:4:5}
e f g h i
=========================================================
说明:echo ${array[@]:4:5}截取时,4表示数组下标开始的位置,5表示截取的长度,如:
[root@zabbix 0514]# echo ${array[@]:4:1}
e
替换数组元素部分内容的代码如下:
[root@zabbix 0514]# array=(1 2 3 1 1)
[root@zabbix 0514]# echo ${array[*]}
1 2 3 1 1
[root@zabbix 0514]# echo ${array[*]/1/b}
b 2 3 b b
========================================================
提示:调用方法为${数组名[@或*]/查找字符/替换字符},该操作不会改变原先数组的内容,
如果需要修改,可以参考上面的例子,重新定义数组。
删除数组元素部分内容的代码如下:
[root@zabbix 0514]# array=(one one1 two two1 three three1 four four1 left)
[root@zabbix 0514]# echo ${array[*]#f*} ==> 删除数组中以f开头的元素中的f
one one1 two two1 three three1 our our1 left
[root@zabbix 0514]# echo ${array[*]##f*} ==> 删除数组中以f开头的元素
one one1 two two1 three three1 left
=======================================================================
[root@zabbix 0514]# echo ${array[*]}
one one1 two two1 three three1 four four1 left
[root@zabbix 0514]# echo ${array[*]%1*} ==> 删除数组中以1结尾的元素中的1
one one two two three three four four left
13.3 shell 数组脚本开发实践
13.3.1 使用循环批量输出数组的元素
范例13-1:使用循环批量输出数组的元素。
方法1:通过C语言型的for循环语句打印数组元素。
[root@zabbix 0514]# cat for_c.sh
#!/bin/bash
array=(1 2 3 4 5)
for((i=0;i<${#array[*]};i++))
do
echo ${array[i]}
done
[root@zabbix 0514]# sh for_c.sh
1
2
3
4
5
方法2:通过普通for循环语句打印数组元素。
[root@zabbix 0514]# cat array_1.sh
#!/bin/bash
array=(1 2 3 4 5)
for n in ${array[*]}
do
echo $n
done
方法3:使用while循环语句打印数组元素。
[root@zabbix 0514]# cat array_while.sh
#!/bin/bash
array=(1 2 3 4 5)
i=0
while ((i<${#array[*]}))
do
echo ${array[i]}
((i++))
done
13.3.2 竖向列举法定义数组元素并批量打印
范例13-2:通过竖向列举法定义数组元素并批量打印。
[root@zabbix 0514]# cat array_menu.sh
#!/bin/bash
array=(
oldboy
oldgirl
moox
tingting
)
for ((i=0;i<${#array[*]};i++))
do
echo "this is num $i ,content: ${array[$i]}"
done
echo -----------------------------
echo "array length: ${#array[*]}"
===================================
[root@zabbix 0514]# sh array_menu.sh
this is num 0 ,content: oldboy
this is num 1 ,content: oldgirl
this is num 2 ,content: moox
this is num 3 ,content: tingting
-----------------------------
array length: 4
范例13-3:将命令结果作为数组元素定义并打印。
[root@zabbix 0514]# ll array
total 0
-rw-r--r-- 1 root root 0 May 14 11:19 1.txt
-rw-r--r-- 1 root root 0 May 14 11:19 2.txt
-rw-r--r-- 1 root root 0 May 14 11:19 3.txt
[root@zabbix 0514]# cat array_ls.sh
#!/bin/bash
dir=($(ls array)) ==> 将ls的结果放到数组中,数组定义:array=(1 2 3 ..)
==> $(ls array) = `ls array`
for ((i=0;i<${#dir[*]};i++))
do
echo "NO.$i : ${dir[$i]}"
done
[root@zabbix 0514]# sh array_ls.sh
NO.0 : 1.txt
NO.1 : 2.txt
NO.2 : 3.txt
13.4 shell 数组的重要命令
(1)定义命令
1.静态数组 array=(1 2 3)
2.动态数组 array=($(ls))或array=(`ls`)
3.数组赋值 array[2]=3
(2)打印命令
1.打印所有元素 ${array[@]} 或 ${array[*]}
2.打印数组长度 ${#array[@]} 或 ${#array[*]}
3.打印单个元素 ${array[i]}
(3)循环打印的常用基本语法
#!/bin/bash
array={
10.0.0.11
10.0.0.22
10.0.0.33
}
==> C语言for循环语法
for ((i=0;i<${#array[*]};i++))
do
echo ${array[$i]}
done
==>普通for循环语法
for n in ${array[*]}
do
echo $n
done
13.5 shell数组相关面试题及实战案例
13.5.1 数组实现循环打印单词
范例13-4:利用bash for循环打印下面这句话中字母数不大于6的单词(某企业面试真题)。
I am oldboy training welcome to my linux class
方法1:通过数组方法来实现。
[root@zabbix 0515]# cat array_length.sh
#!/bin/bash
arr=(I am oldboy training welcome to my linux class )
for ((i=0;i<${#arr[*]};i++))
do
if [ ${#arr[$i]} -lt 6 ];then
echo ${arr[$i]}
fi
done
echo ------------------------
for word in ${arr[*]}
do
if [ `expr length $word` -lt 6 ]
then
echo $word
fi
done
方法2:使用for循环列举取值列表法。
[root@zabbix 0515]# cat array_length.sh
#!/bin/bash
#for word in I am oldboy training welcome to my linux class
chars="I am oldboy training welcome to my linux class"
for word in $chars
do
if [ `echo $word|wc -L` -lt 6 ]
then
echo $word
fi
done
方法3:通过awk循环实现。
[root@zabbix 0515]# chars="I am oldboy training welcome to my linux class"
[root@zabbix 0515]# echo $chars |awk '{for(i=1;i<=NF;i++)if(length($i)<=6) print $i}'
I
am
oldboy
to
my
linux
class
13.5.2 数组实现批量检查多个网址异常
范例13-5:批量检查多个网站地址是否正常。
要求: 1)使用Shell数组的方法实现,检测策略尽量模拟用户访问。 2)每10秒进行一次全部检测,无法访问的输出报警。 3)待检测的地址如下。 http://blog.moox.com http://blog.moox.org http://www.moox.com http://10.0.0.71
解题思路: 1)把URL定义成数组,形成函数。 2)编写URL检查脚本函数,传入数组的元素,即URL。 3)组合实现整个案例,编写main主函数(即执行函数),每隔10秒检查一次。 下面的参考答案采用了Shell数组的方法,同时检测多个URL是否正常,并给出专业的展示效果
[root@zabbix 0515]# cat array_url.sh
#!/bin/bash
. /etc/init.d/functions
check_count=0
url_list=(
http://blog.moox.com
http://blog.moox.org
http://www.moox.com
http://10.0.0.71
)
function wait(){
echo -n "3 second later , check url would be run."
for ((i=3;i>=1;i--))
do
echo -n " $i "
sleep 1
done
}
function check_url(){
wait
for ((i=0;i<`echo ${#url_list[*]}`;i++))
do
wget -o /dev/null -T 3 --tries=1 --spider ${url_list[$i]} > /dev/null 2>&1
if [ $? -eq 0 ];then
action $"${url_list[$i]}" /bin/true
else
action $"${url_list[$i]}" /bin/false
fi
done
((check_count++))
}
function main(){
while true
do
check_url
echo "--------check count: ${check_count}"
sleep 10
done
}
main
13.6 合格运维人员必会的脚本列表
作为一个合格的运维人员,需要掌握的脚本知识列表如下: 1)系统及各类服务的监控脚本,例如:文件、内存、磁盘、端口,URL监控报警等。 2)监控网站目录下的文件是否被篡改,以及当站点目录被批量篡改后如何批量恢复它们的脚本。 3)各类服务Rsync、Nginx、MySQL等的启动及停止专业脚本(使用chkconfig管理)。 4)MySQL主从复制监控报警,以及自动处理不复制故障的脚本。 5)一键配置MySQL多实例、一键配置MySQL主从部署的脚本。 6)监控HTTP、MySQL、Rsync、NFS、Memcached等服务是否异常的生产脚本。 7)一键软件安装及优化的脚本,比如LANMP、Linux一键优化,一键数据库安装、优化等。 8)MySQL多实例启动脚本,分库、分表自动备份脚本。 9)根据网络连接数及Web日志PV数封IP的脚本。 10)监控网站的PV及流量,并且对流量信息进行统计的脚本。 11)检查Web服务器多个URL地址是否异常的脚本,要是可以批量处理且通用的脚本。 12)对系统的基础配置一键优化的脚本。 13)TCP连接状态及IP统计报警的脚本。 14)批量创建用户并设置随机8位密码的脚本。