shell编程企业级实战(2)
Vim配置文件.vimrc
if 条件语句
if是最常见的条件判断语句
例1:如果不存在/backup目录就创建。 [root@web-01 /server/tools]# vim 07-01.sh
#!/bin/bas
path=/backup
[ -d $path ] || mkdir $path -p
# 相当于
# :冒号表示什么也不干
if [ -d $path ]
then
:
else
mkdir $path -p
fi
# 或者
[ !-d $path ] && mkdir /backdir -p
# 相当于
if [ !-d $path ]
then
mkdir /backdir -p
if
"07-01.sh" 18L, 248C writte
vim命令:替换:%s#/backup#$path#g
例2:开发Shell脚本判断系统剩余内存的大小,如果低于100MB就提示内存不足,否则提示内存充足。 考查if双分支: 分析: 1)提取系统内存。 2)if判断, [root@web01 07]# cat 07_02.sh #!/bin/bash ############################################################## # File Name: 07_02.sh # Version: V1.0 # Author: pizza # Created Time : 2018-06-06 22:58:54 # Description: ############################################################## mem=`free -m|awk 'NR==3{print $NF}'` if [ $mem -lt 1000 ] then echo "内存严重不足。" else echo "内存还够" fi
在第一章的中添加了内存不足发邮件的例子 例3:分别使用变量定义、read读入及脚本传参方式实现比较2个整数的大小。 1)变量定义: a=6 b=2 2)read读入: read -p "请输入两个数字:" a b 3)传参: 分析: 大于 等于 小于 #!/bin/bash
##############################################################
# File Name: 07-03.sh
# Version: V1.0
# Author: pizza
# Created Time : 2019-03-28 21:20:46
# Description:
##############################################################
# 第一种,传参
a=6
b=7
# 第二种,read
read -p "请输入两个数字" a b
# 第三种,参数
$a=$1
$b=$2
# 判断输入
# 1、判断数字是不是够,判断b是不是空,或者使用$#
# 2、判断是不是整数,利用expr
# 3、
if [ $a -gt $b ]
then
echo "$a>$b"
elif [ $a -lt $b ]
then
echo "$a<$b"
else
echo "$a=$b"
fi
例4:打印一个菜单如下,当用户选择对应的数字时,就执行对应项的应用。 1.install lamp 2.install lnmp 3.exit 第一章已讲解: bash内置核心命令read的企业级应用实践 read企业应用 [root@web01 scripts]# cat select1.sh #!/bin/bash cat <<EOF 1.install lamp 2.install lnmp 3.exit EOF read -p "请选择一个序号(必须是数字):" num #1.判断是否为整数 expr 2 + $num &>/dev/null if [ $? -ne 0 ] then echo "Usage:$0 {1|2|3}" exit 1 fi #2.判断执行处理 if [ $num -eq 1 ] then echo "install lamp..." elif [ $num -eq 2 ] then echo "install lnmp..." elif [ $num -eq 3 ] then echo "bye." exit else echo "Usage:$0 {1|2|3}" exit 1 fi
Shell函数的知识与实践
函数的作用就是将程序里多次被调用的相同代码组合起来,并为其取个名字。其他所有想重复调用这部分代码的复方都只需要调用这个这个名字就可以了。当需要修稿这部分重复代码的时候,也只需要改变函数内的一份代码即可实现所有的修改,也可以把函数独立写到文件里面,当需要调用的时候,再加载进来。
函数的语法体
oldboy() { echo "I am oldboy." } function oldgirl { echo "I am oldgirl." } test() { echo "Hello world." } oldboy oldgirl
[root@web-01 ~]# sh test_hanshu.sh
I am oldboy.
I am oldgirl.
Hello world.
[root@web-01 ~]#
向函数传参
带参数的函数编写执行 oldboy() { echo "I am $1." } oldboy oldboy 将函数传参转为脚本传参 oldboy() { echo "I am $1." } oldboy $1
函数和执行函数分离
./etc/init.d/function
pizza $1
Shell函数的执行注意事项
企业案例:通过脚本传参的方式,检查Web 网站URL是否正常。
wget命令: --spider 模拟爬虫 -q 安静访问 -o /dev/null 不输出 -T --timeout 超时时间 -t --tries 重试次数 [root@web01 ~]# wget --spider -T 5 -q -o /dev/null -t 2 www.baidu.com [root@web01 ~]# echo $? 0 curl命令: -I 看响应头 -s 安静的 安静模式。不显示进度表或错误信息。使cURL 不反馈信息。 -o /dev/null 不输出 -w %{http_code} 返回状态码,200
-m 超时时间
[root@web01 ~]# curl www.baidu.com -s &>/dev/null [root@web01 ~]# echo $? 0 [root@web01 ~]# curl -I -m 5 -s -w "%{http_code}\n" -o /dev/null www.baidu.com 200 不用函数的实现写法 #!/bin/sh if [ $# -ne 1 ] then echo $"usage:$0 url" exit 1 fi wget --spider -q -o /dev/null --tries=1 -T 5 $1 #<==-T指定超时时间,这里的$1为脚本的参数。 if [ $? -eq 0 ] then echo "$1 is yes." else echo "$1 is no." fi 高端专业的函数写法: [root@oldboy ~]# cat checkurl.sh #!/bin/bash ############################################################## # File Name: checkurl.sh # Version: V1.0 # Author: oldboy # Organization: www.oldboyedu.com # Created Time : 2018-06-07 18:29:19 # Description: ############################################################## usage(){ echo "Usage:$0 url" exit 1 } checkurl(){ wget -q -o /dev/null -t 2 -T 5 $1 if [ $? -eq 0 ] then echo "$1 is ok" else echo "$1 is fail" fi } main(){ if [ $# -ne 1 ] then usage fi checkurl $1 } main $* [root@oldboy scripts]# cat 8_5_1.sh #!/bin/sh function usage() { #<==帮助函数 echo $"usage:$0 url" exit 1 } function check_url() { #<==检测URL函数。 wget --spider -q -o /dev/null --tries=1 -T 5 $1 #<==这里的$1就是函数传参。 if [ $? -eq 0 ] then echo "$1 is yes." else echo "$1 is no." fi } function main() { #<==主函数。 if [ $# -ne 1 ] #<==如果传入的多个参数,则打印帮助函数,提示用户。 then usage fi check_url $1 #<==接收函数的传参,即把结尾的$*传到这里。 } main $* #<==这里的$*就是把命令行接收的所有参数作为函数参数传给函数内部,常用手法。
CASE结构条件句
几乎所有的case都可以用if替代 case "$1" in 1) dddd ;; 2) dddd ;; *) dddd esac 企业应用: 启动脚本 read 读入 菜单选择。 范例9_2:执行shell脚本,打印一个如下的水果菜单: 1.apple 2.pear 3.banana 4.cherry 当用户输入对应的数字选择水果的时候,告诉他选择的水果是什么,并给水果单词加上一种颜色(随意),要求用case语句实现。 范例9_3:给内容加不同的颜色。 内容的颜色用数字表示,范围为30-37,每个数字代表一种颜色。代码如下: echo -e "\033[30m 黑色字 \033[0m" #<==30m表示黑色字。 echo -e "\033[31m 红色字 \033[0m" #<==31m表示红色字。 echo -e "\033[32m 绿色字 \033[0m" #<==32m表示绿色字。 echo -e "\033[33m 棕色字 \033[0m" #<==33m表示棕色字(brown),和黄色字相近。 echo -e "\033[34m 蓝色字 \033[0m" #<==34m表示蓝色字。 echo -e "\033[35m 洋红字 \033[0m" #<==35m表示洋红色字(magenta),和紫色字相近。 echo -e "\033[36m 蓝绿色 \033[0m" #<==36m表示蓝绿色字(cyan),和浅蓝色字相近。 echo -e "\033[37m 白色字 \033[0m" #<==37m表示白色字。 说明:不同的数字对应的字体颜色,见系统帮助(来源man console_codes命令的结果)。 范例9_6: 给输出的字符串加不同的背景颜色。 字的背景颜色对应的数字范围为40-47,代码如下。 echo -e "\033[40;37m 黑底白字\033[0m" #<==40m表示黑色背景。 echo -e "\033[41;37m 红底白字\033[0m" #<==41m表示红色背景。 echo -e "\033[42;37m 绿底白字\033[0m" #<==42m表示绿色背景。 echo -e "\033[43;37m 棕底白字\033[0m" #<==43m表示棕色背景(brown),和黄色背景相近。 echo -e "\033[44;37m 蓝底白字\033[0m" #<==44m表示蓝色背景。 echo -e "\033[45;37m 洋红底白字\033[0m" #<==45m表示洋红色背景(magenta),和紫色背景相近。 echo -e "\033[46;37m 蓝绿底白字\033[0m" #<==46m表示蓝绿色背景(cyan),和浅蓝色背景相近。 echo -e "\033[47;30m 白底黑字\033[0m" #<==47m表示白色背景。
创建case3.sh,定义函数 ,执行函数color $*
创建case4.sh,用.或者source调用函数,打印菜单,输入数字,显示不同颜色的字体 范例9_10:利用case语句开发Rsync服务启动停止脚本,本例采用case语句以及新的思路来实现。 分析: 启动: rsync --daemon 停止: pkill rsync killall rsync kill 进程号 ---->最专业的方法 /etc/init.d/rsyncd {start|stop|restart} case
rsync.sh简单版
case "$1" in start) rsync --deamon if [ $? -eq 0 ] then echo "rsync startup ok" else echo "rsync startup fail" fi ;; stop) killall rsync if [ $? -eq 0 ] then echo "rsync stop ok" else echo "rsync stop fail" fi ;; restart) killall rsync && sleep 1 && rsync --deamon if [ $? -eq 0 ] then echo "rsync restart ok" else echo "rsync restart fail" fi ;; *) echo "usage:$0 {start|stop|restart}" exit 1 esac
升级版
start(){ rsync --deamon retval=$? if [ $retval -eq 0 ] then echo "rsync startup ok" return $retval else echo "rsync startup fail" return $retval fi } stop(){ killall rsync retval=$? if [ $? -eq 0 ] then echo "rsync stop ok" 9,1 Top return $retval else echo "rsync restart fail" return $retval fi } case "$1" in start) start # 为了向外传值 retval=$? ;; stop) stop retval=$? ;; restart) restart retval=$? ;; *) echo "usage:$0 {start|stop|restart}" exit 1 esac
想要使用chkconfig(man ckhconfig),找到这些信息
RUNLEVEL FILES Each service which should be manageable by chkconfig needs two or more commented lines added to its init.d script. The first line tells chkconfig what runlevels the service should be started in by default, as well as the start and stop priority levels. If the service should not, by default, be started in any runlevels, a - should be used in place of the runlevels list. The second line contains a description for the ser‐ vice, and may be extended across multiple lines with backslash continuation. For example, random.init has these three lines: # chkconfig: 2345 20 80 表示在2345这几个启动级别上 启动顺序排20 停止顺序排80 # description: Saves and restores system entropy pool for \ # higher quality random number generation.
在脚本首行加入
#!/bin/bash # chkconfig: 2345 20 80 # description: rsync start stop and restart
将脚本移动到/etc/init.d/下,并添加执行权限,添加到chkconfig中才能使用
[root@web-01 /server/tools]# mv /etc/init.d/rsync_up.sh /etc/init.d/rsyncd [root@web-01 /server/tools]# chmod +x /etc/init.d/rsyncd [root@web-01 /server/tools]# chkconfig --list rsyncd Note: This output shows SysV services only and does not include native systemd services. SysV configuration data might be overridden by native systemd configuration. If you want to list systemd services use 'systemctl list-unit-files'. To see services enabled on particular target use 'systemctl list-dependencies [target]'. service rsyncd supports chkconfig, but is not referenced in any runlevel (run 'chkconfig --add rsyncd') [root@web-01 /server/tools]# chkconfig --add rsyncd [root@web-01 /server/tools]# chkconfig --list rsyncd Note: This output shows SysV services only and does not include native systemd services. SysV configuration data might be overridden by native systemd configuration. If you want to list systemd services use 'systemctl list-unit-files'. To see services enabled on particular target use 'systemctl list-dependencies [target]'. rsyncd 0:off 1:off 2:on 3:on 4:on 5:on 6:off
更好一些,调用了系统函数,action。并优化了重复停止的输出
#!/bin/bash # chkconfig: 2345 20 80 # description: rsync start stop and restart ############################################################## # File Name: syncd.sh # Version: V1.0 # Author: pizza # Created Time : 2019-03-29 22:06:46 # Description: ############################################################## . /etc/init.d/functions start(){ rsync --deamon retval=$? if [ $retval -eq 0 ] then action "rsync startup ok" /bin/true return $retval else action "rsync startup fail" /bin/false return $retval fi } 1,1 Top return $retval fi } case "$1" in start) start # 我了向外传值 retval=$? ;; stop) stop retval=$? ;; restart) restart retval=$? ;; *) echo "usage:$0 {start|stop|restart}" exit 1 esac
开发和系统媲美的脚本
跟完善的查看企业实践题第11题-制作MySQL脚本
92,0-1 Bot #!/bin/bash # chkconfig: 2345 20 80 # description: rsync start stop and restart ############################################################## # File Name: syncd.sh # Version: V1.0 # Author: pizza # Created Time : 2019-03-29 22:06:46 # Description: ############################################################## # 定义锁文件 lockfile=/var/lock/subsys/rsyncd # 定义变量,指定rsyncd的的pid,是需要自己rsync的conf中去创建 #[root@web-01 /server/tools]# vim /etc/rsyncd.conf #pid file=/var/run/rsyncd.pid srsync_pid_file_path=/var/run/rsyncd.pid . /etc/init.d/functions start(){ rsync --deamon retval=$? if [ $retval -eq 0 ] then action "rsync startup ok" /bin/true touch $lockfile return $retval else action "rsync startup fail" /bin/false return $retval fi } stop(){ # 为了在重复停止操作的时候,不提示,将其扔到黑洞 if test -s "$rsyncd_pid_file_path" then rsyncd_pid=`cat $rsyncd_pid_file_path` # 判断进程号是不是真实存在 if (kill -0 $rsyncd_pid &>/dev/null) then kill $rsyncd_pid retval=$? if [ $? -eq 0 ] then action "rsync stop ok" /bin/true rm -f $lockfile return $retval else action "rsync stop fail" /bin/false return $retval fi else echo "rsyncd process is not exist." return 2 fi else echo "$srsync_pid_file_path is not exits,or rsyncd doesnot start" fi } restart(){ killall rsync && sleep 1 && rsync --deamon retval=$? if [ $? -eq 0 ] then action "rsync restart ok" /bin/true return $retval else action "rsync restart fail" /bin/false return $retval fi } case "$1" in start) start # 我了向外传值 retval=$? ;; stop) stop retval=$? ;; restart) restart retval=$? ;; *) echo "usage:$0 {start|stop|restart}" exit 1 esac
case总结
1、case语句和if条件句的使用性
case语句比较适合变量较少且为固定的数字或者字符串集合的情况(非不确定内容,如范围)
2、if和case的常用应用场景
case只要写服务的启动脚本,一般情况下,传参不同且具有少量的字符串,其使用范围较窄
if就是取值判断、比较,应用比case更广,几乎所有的case语句都可以用if条件语句实现。
3、case语句的特点和优势
它相当于多分支的if/elif/else语句,但是case语句的优势是更规范。易读
while循环
循环语句命令常用于重复执行一条指令或一组指令,直到条件不满足停止,Shell脚本语言的循环语句常见的有while、until、for以及select循环语句。 while循环语句主要用来重复执行一组命令或语句,在企业实际应用中,常用于守护进程或持续运行的程序,除此以外,大多数循环都会用后文即将讲解 的for循环语句。
while true do uptime >> /tmp/uptime.log sleep 2 # 暂停2s usleep 2000 # 微秒 done
脚本进程管理命令
后台运行 &、nohup、screen(运维人员)
为什么要用后台运行,防止你在执行重要命令的时候,网络宕机
进程管理的其他常见命令
范例1:请使用while循环对下面的脚本进行修改,是的当执行脚本时,每次执行完脚本后,不退出脚本,而是提示用户输入
while true do read -p "请输入两个数字:" a b if [ -z $b ] then echo "请输入两个数字" continue fi expr 10 + $a + $b &>/dev/null if [ $? -ne 0 ] then echo "请输入两个数字" continue fi echo "a+b=$(($a+$b))" done
范例2:猜数字游戏。首先让系统随机生成一个数字,给这个数字定一个范围(1-60),让用户输入猜的数字,对输入进行判断,如果不符合要求,就给予高或低的提示,猜对后则给出猜对用的次数,请用while语句实现。
提示:可以赋予一个猜水果的价格游戏。
1、给数字定范围(1-60) RANDOM随机数,它的范围是0-32767 [root@web-01 /server/tools]# echo $RANDOM 9279 为随机数取模。控制在1-60 [root@web-01 /server/tools]# echo $((RANDOM%60)) 11 2、用户输入数字 read -p “请输入数字:” num 3、对比,直到正确才推出 while 4、代码: random="$(($RANDOM%60))" #做计数 count=0 echo $random while true do read -p "请输入数字:" num ((count++)) if [[ $num -lt $random ]] then echo "低了" continue elif [[ $num -gt $random ]] then echo "高了" continue elif [[ $num -eq $random ]] then echo "恭喜你,猜对了,一共猜了$count次" exit 0 else echo "请输入数字" fi done
还可以加入函数,其他的限制内判断,使脚本更完善
范例3:分析Apache访问日志(access_2010-12-8.log),把日志中每行的访问字节数对应字段数字相加,计算出总的访问量。给出实现程序,请用while循环实现。(3分钟)
方式1:在while循环结尾done通过输入重定向指定读取的文件。 while read line do cmd done<FILE 方式2:使用cat读取文件内容,然后通过管道进入while循环处理。 cat FILE_PATH|while read line do cmd done 方式3:采用exec读取文件后,然后进入while循环处理。 exec <FILE sum=0 while read line do cmd done
体验
while read line do echo $line sleep 1 done < ./while_01.sh ~ ~ "while_readline.sh" [New] 13L, 320C written [root@web-01 /server/tools]# sh while_readline.sh #!/bin/bash ############################################################## # File Name: while_01.sh # Version: V1.0 # Author: pizza # Created Time : 2019-03-30 07:19:26 # Description: ############################################################## while true do uptime >> /tmp/uptime.log sleep 2 # 暂停2s usleep 2000 # 微秒 done
体验2
[root@web-01 /server/tools]# seq 10 >>num.log 脚本 sum=0 while read line do ((sum+=line)) done<./num.log echo $sum 执行 [root@web-01 /server/tools]# sh while_num_add.sh 55
答案
sum=0 awk '{print $10}' access_2010-12-8.log |grep -v -|while read line do ((sum+=line)) done echo sum # 已经计算了,但是最后的结果是0 # 这是因为执行了子shell # 使用下面的方法可以成功输出 sum=0 awk '{print $10}' access_2010-12-8.log |grep -v - > any_sum.log do ((sum+=line)) done<./any_sum.log echo sum
小结
1、while循环的特长是执行守护进程,以及实现我们希望循环不退出持续执行的应用
擅长用于频率小于1分钟循环处理,其他的while循环几乎都可以被for以及定时任务crond替代
2、if、for最常用,然后是while(守护进程),case(服务启动脚本)
Shell脚本中各个语句的使用场景
1、条件表达式,用于简短的条件判断及输出(文件是否存在,字符串是否为空)
2、if取值判断,多用于不同值数量较少的情况
3、for正常的循环应用处理,最常用
4、while多用于守护进程,无限循环(要加sleep,usleep,控制pinlv)应用
5、case 多用于服务启动脚本,打印菜单可用select语句,不过很少用,都用cat的here文档方法替代
6、函数用途主要指编码逻辑清晰,减少重复语句开发
for循环
for循环语句和while循环语句类似,但for循环语句主要用于执行次数有限的循环,而不是用于守护进程以及无限循环。for循环语句常见的语法有两种, 下面将在不同的语法中对for循环语句进行详尽的讲解。
..
范例1:用for循环竖向打印1、2、3、4、5共5个数字。 范例2:通过开发脚本实现仅设置sshd rsyslog crond network sysstat服务开机自启动。 范例3:计算从1加到100之和。 范例4:在Linux下批量修改文件名,将文件名中的“_finished”去掉。 准备测试数据,如下。 [root@oldboy test]# mkdir /oldboy -p [root@oldboy test]# cd /oldboy [root@oldboy oldboy]# touch stu_102999_1_finished.jpg stu_102999_2_finished.jpg stu_102999_3_finished.jpg [root@oldboy oldboy]# touch stu_102999_4_finished.jpg stu_102999_5_finished.jpg [root@oldboy oldboy]# ls -l 总用量 0 -rw-r--r-- 1 root root 0 9月 5 10:43 stu_102999_1_finished.jpg -rw-r--r-- 1 root root 0 9月 5 10:43 stu_102999_2_finished.jpg -rw-r--r-- 1 root root 0 9月 5 10:43 stu_102999_3_finished.jpg -rw-r--r-- 1 root root 0 9月 5 10:43 stu_102999_4_finished.jpg -rw-r--r-- 1 root root 0 9月 5 10:43 stu_102999_5_finished.jpg ls *.jpg|awk -F "_finished" '{print "mv",$0,$1$2}'|bash rename "_finished" "" *.jpg for file in `ls ./*.jpg` do mv $file `echo ${file/_finished/}` done
范例1答案
for n in 1 2 3 4 5 或者 {1..5} 或者seq 5 do echo $n done echo "---------" for ((i=1;i<=5;i++)) do echo $i done "for_printnum.sh" [New] 18L, 350C written [root@web-01 /server/scripts]# sh for_printnum.sh 1 2 3 4 5 --------- 1 2 3 4 5
范例2答案
for name in sshd rsyslog crond network sysstat do echo "chkconfig $name on" done
相当于在命令行执行
[root@web-01 /server/scripts]# chkconfig |grep 3:on |awk '{print "chkconfig",$1,"off"}'|bash
范例3
1、for循环 2、while循环 3、算法
范例4
1、mv $file 'echo ${file/_finished/}' 2、不用for循环 [root@web-01 /server/scripts]# ls *.jpg|awk -F "_finished" '{print $0,$1$2}' 3、rename from to file rename _finished "" *.jpg
循环控制语句break、continue、exit、return
在上述命令中,break、continue在条件语句及循环语句(for、while、if等)中用于控制程序的走向,
而exit则用于终止所有语句并退出当前脚本,除此之外,exit还可以返回上一次程序或命令的执行状态值给当前Shell;
return类似exit,只不过return仅用于在函数内部返回函数执行的状态值。
break n 如果省略n表示跳出整个循环,n 表示跳出循环的层数 continue n 如果省略n表示跳过本次循环,忽略本次循环的剩余代码,进入循环的下一次循环。n 表示退到第n层继续循环 exit n 退出当前shell程序,n为上一次程序执行的状态返回值。n也可以省略,再下一个shell里可通过$?接收exit n的n值 return n 用于在函数里,作为函数的返回值,用于判断函数执行是否正确。再下一个shell里可通过$?接收exit n的n值
Shell编程数组应用实践
为什么会产生shell数组
通常在开发Shell脚本时,我们定义变量采用的形式为a=1;b=2;c=3,可如果有多个变量呢?这时再一个一个定义很费劲,并且要是有多个不确定的变量内容,也难以进行变量定义,此外,快速读取不同变量的值也是一件很痛苦的事情,于是数组就诞生了,它就是为了解决上述问题而来的。
什么是Shell数组
如果读者有过其他语言的编程经历,那么想必会熟悉数组的概念。简单地说,Shell的数组就是把有限个元素(变量或字符内容)用一个名字命名,然后用编号对它们进行区分的元素集合。这个名字就称为数组名,用于区分不同内容的编号就称为数组下标。组成数组的各个元素(变量)称为数组的元素,有时也称为下标变量。
有了Shell数组后,就可以用相同名字引用一系列变量及变量值,并通过数字(索引)来识别使用它们。在许多场合,使用数组可以缩短和简化程序开发。
数组的本质还是变量,是特殊的变量形式
array=(1 2 3 4 5)
Shell数组的定义***** 方法1:推荐,用小括号把变量值括起来赋值给数组变量,中间用空格分割 array=(one two three four) 方法2:用小括号把变量值括起来,同时采用键值对的形式赋值 array=([0]=one [1]=two [2]=three [3]=four) 方法3:通过分别定义数组变量的方式 [root@web01 ~]# array[0]=one [root@web01 ~]# array[1]=two [root@web01 ~]# array[2]=three [root@web01 ~]# array[3]=four [root@web01 ~]# echo ${array[@]} one two three four 方法4:命令的结果放到数组里,推荐。动态定义数组变量,使用命令的输出结果作为数组的内容 array=(`ls /server/scripts`) 说明:还可以使用declare -a array来定义数组类型,但是比较少这样用。 操作数组元素 打印单个数组元素用${数组名[下标]},当未指定数组下标时,数组的下标是从0开始。 使用*或者@可以得到整个数组内容。 用${#数组名[@或*]}可以得到数组长度,这和前文讲解的变量子串知识是一样的,因为数组也是变量,只不过是特殊的变量,因此也适合变量的子串替换等知识。 读取数组内容:***** [root@web01 ~]# array=( 1 2 3 4 5) [root@web01 ~]# echo ${array[0]} 1 [root@web01 ~]# echo ${array[1]} 2 [root@web01 ~]# echo ${array[2]} 3 [root@web01 ~]# echo ${array[3]} 4 [root@web01 ~]# echo ${array[4]} 5 [root@web01 ~]# echo ${array[5]} [root@web01 ~]# echo ${array[*]} 1 2 3 4 5 [root@web01 ~]# echo ${array[@]} 1 2 3 4 5 [root@web01 ~]# echo ${#array[@]} 5 [root@web01 ~]# echo ${#array[*]} 5 给数组增加内容: [root@web01 ~]# array[5]=oldboy <==增加下标为5的数组元素。 [root@web01 ~]# echo ${#array[*]} 6 [root@web01 ~]# echo ${array[*]} 1 2 3 4 5 oldboy 删除数组元素: [root@web01 ~]# unset array[1] [root@web01 ~]# echo ${array[*]} 1 3 4 oldboy [root@web01 ~]# unset array[0] [root@web01 ~]# echo ${array[*]} 3 4 oldboy 数组赋值: [root@web-01 /server/scripts]# array[4]=999 [root@web-01 /server/scripts]# echo ${array[*]} 1 2 3 4 999 6 数组的删除: 因为数组本质上还是变量,因此可通过“unset 数组[下标]”清除相应的数组元素, 如果不带下标,表示清除整个数组的所有数据。 [root@web-01 /server/scripts]# unset array[1] 删除单个元素 [root@web-01 /server/scripts]# echo ${array[*]} 1 3 4 999 6 [root@web-01 /server/scripts]# unset array 删除整个数组 [root@web-01 /server/scripts]# echo ${array[*]} 没有数据输出了 数组内容的截取和替换: 这里和前文变量子串的替换是一样的,因为数组是特殊的变量 [root@web-01 /server/scripts]# echo ${array[*]:1:3} 从下表为1的元素截取3个元素 2 3 4 替换 和sed命令,和变量子字符串的替换 很像,是一样的 [root@web-01 /server/scripts]# echo ${array[*]/1/999} 999 2 3 4 5 6 7 8 9 9990 [root@web-01 /server/scripts]# echo ${array[*]} 该操作不会改变原数组,要改变请参考赋值修改 1 2 3 4 5 6 7 8 9 10 数组也是变量,因此也适合于前面讲解过的变量的子串处理的功能应用。 数组的其他相关知识通过man bash然后搜Arrays来了解。 数组元素部分内容的删除如下: [root@oldboy data]# array=(one two three four five) [root@oldboy data]# echo ${array[@]} one two three four five [root@oldboy data]# echo ${array[@]#o*} #<==从左边开始匹配最短的,并删除。 ne two three four five [root@oldboy data]# echo ${array1[@]##o*} #<==从左边开始匹配最长的,并删除。 two three four five [root@oldboy data]# echo ${array[@]%f*} #<==从右边开始匹配最短的,并删除。 one two three [root@oldboy data]# echo ${array[@]%%f*} #<==从右边开始匹配最长的,并删除。 one two three 使用for循环打印数组元素 array=(1 2 3 4 5) for n in ${array[*]} do echo $n done echo ===================== #i为数组下标 for ((i=0;i<${#array[*]};i++)) do echo ${array[i]} done array=([1]=one [2]=two [3]=three) array[0]=a;array[1]=b;array[2]=c array=($(命令)) 或 array=(`命令`)
shell数组企业面试题
1、利用bash for循环打印下面这句话中字母数不大于6的单词(某企业面试真题)。
I am pizza teacher welcome to luffy training class
array=(I am oldboy teacher welcome to oldboy training class) for word in ${array[*]}
#或者
#for ((i=0;i<=${array[*];i++})) do if [ ${#word} -lt 6 ]
# if [ ${#array[i]} -lt 6 ] then echo $word
# echo array[i] fi done
第十四章 编程规范 第十五章 脚本调试 第十六章 vim配置 第十七章 trap 第十八章 expect 第十九章 企业案例实战 第十九章 企业面试题1: 分析: 1、获取随机小写字符。 echo $RANDOM$(date +%N)|md5sum|tr "[0-9]" "a-z"|cut -c 2-11 2、for循环 企业面试题3: 1、01..10 [root@db03 ~]# seq -w 10 01 02 03 04 05 06 07 08 09 10 [root@db03 ~]# echo ${01..10} -bash: ${01..10}: bad substitution [root@db03 ~]# echo {01..10} 01 02 03 04 05 06 07 08 09 10 2、echo $RANDOM|md5sum|cut 1-8 3、for循环批量设置用户和密码。 企业面试题4: 1、如何判断机器是否是活的。 ping 10.0.0.53 -c 2 -W 3 有返回。 nmap -sP 10.0.0.0/24 2.for循环 #!/bin/sh CMD="nmap -sP" Ip="10.0.0.0/24" $CMD $Ip|awk '/Nmap scan report for/ {print $NF}' http://blog.51cto.com/oldboy/1632876 10,11,18,19,20,13,6