shell脚本编程2:
在上节我们介绍了shell脚本编程,但只是介绍了基础的内容,下面将为大家介绍shell的脚本的高级用法,判断与循环.判断分为两种:if语句和case语句;循环分为三种:for语句,while语句,until语句,select语句
判断语句:
在脚本的编写中,我们要使用大量的数据和命令,但对于使用的数据,我们要想办法进行验证,,判断数据的正确性,来达到我们编写脚本的目的.于是判断机制尤为重要,来看下两个判断语句.
1.if语句
特点:
选择执行
判断条件为真,执行后面语句;否则,执行else后的语句
if可嵌套
语法:
单分支:
if 判断条件: then
条件为真的分支代码
fi
双分支:
if 判断条件; then
条件为真的分支代码
else
条件为假的分支代码
fi
多分支:
if CONDITION1; then
if-true
elif CONDITION2; then
if-ture
elif CONDITION3; then
if-ture
…
else
all-false
fi
注意:逐条件进行判断,第一次遇为“真”条件时,执行其分支,而后结束整个if语句
实例:
根据命令的退出状态来执行命令 if ping -c1 -W2 station1 &> /dev/null; then echo 'Station1 is UP' elif grep "station1" ~/maintenance.txt &> /dev/null ;then echo 'Station1 is undergoing maintenance‘ else echo 'Station1 is unexpectedly DOWN!' exit 1 fi
2.case语句
特点:
1.风格:
case支持glob风格的通配符:
*: 任意长度任意字符
?: 任意单个字符
[]:指定范围内的任意单个字符
a|b: a或b
2.配合死循环使用
语法:
case 变量引用 in
PAT1)
分支1
;;
PAT2)
分支2
;;
…
*)
默认分支
;;
esac
实例:
case $input in [yY][eE][sS]|[yY]) echo " user enter input is yes" ;; [Nn][oO]|[nN]) echo " user enter input is no" ;; [oO][tT]|[oO]) echo " user enter input is other" ;; *) exit 2 ;; esac
循环语句:
在编写脚本时,我们会遇到批量的操作,对于行数,数量等有规律的数据,我们可以使用循环的方法,来简化我们的脚本,也会使我们的的思路更加清晰.来认识下四个循环语句.
循环执行
将某代码段重复运行多次
重复运行多少次:
循环次数事先已知
循环次数事先未知
有进入条件和退出条件
-
for语句
-
语法
for 变量名 in 列表;do
循环体
done -
执行机制
依次将列表中的元素赋值给“变量名” ; 每次赋值后即执行一次循环体; 直到列表中的元素耗尽,循环结束
-
列表生成方式
(1) 直接给出列表
(2) 整数列表:
(a) {start..end}
(b) $(seq [start [step]] end)
(3) 返回列表的命令 $(COMMAND)
(4) 使用glob, 如: *.sh
(5) 变量引用;$@, $ -
特殊用法
双小括号方法,即((…))格式,也可以用于算术运算
双小括号方法也可以使bash Shell实现C语言风格的变量操作
#I=10
#((I++))for循环的特殊格式:
for ((控制变量初始化;条件判断表达式;控制变量的修正表达式))
do
循环体
done
控制变量初始化:仅在运行到循环代码段时执行一次
控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断 -
for (i=1;i<=100;i++) do echo $i done
-
while语句
-
语法
while CONDITION; do
循环体
done -
执行机制
-
until语句
-
语法
until CONDITION; do
循环体
done -
执行机制
CONDITION:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件为“ true”,则执行一次循环;直到条件测试状态为“ false”终止循环 因此: CONDTION一般应该有循环控制变量;而此变量的值
会在循环体不断地被修正
进入条件: CONDITION为true;
退出条件: CONDITION为false
c.特殊用法
while循环的特殊用法(遍历文件的每一行):
while read line; do
循环体
done < /PATH/FROM/SOMEFILE
依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将行赋值给变量line
练习:
扫描/etc/passwd文件每一行,如发现GECOS字段为空,则填充用户名和单位电话为62985600,并提示该用户的GECOS信息修改成功
进入条件: CONDITION 为false
退出条件: CONDITION 为true
4.select语句
a.语法
select variable in list
do
循环体命令
done
b.执行机制
select 循环主要用于创建菜单,按数字顺序排列的菜单项将显示在标准错误上,并显示PS3 提示符,等待用户输入
用户输入菜单列表中的某个数字,执行相应的命令
用户输入被保存在内置变量 REPLY 中。
c.特殊用法
select 是个无限循环,因此要记住用 break 命令退出循环,或用 exit 命令终止脚本。也可以按 ctrl+c退出循环。
select 经常和 case 联合使用
与 for 循环类似,可以省略 in list , 此时使用位置参量
在循环中,有些语句,可以实现对循环过程的控制.
-
continue
用于循环体中
continue [N]:提前结束第N层的本轮循环,而直接进入下一轮判断;最内层为第1层
while CONDTIITON1; do
CMD1
…
if CONDITION2; then
continue
fi
CMDn
…
done -
break
用于循环体中
break [N]:提前结束第N层循环, 最内层为第1层
while CONDTIITON1; do
CMD1
…
if CONDITION2; then
break
fi
CMDn
…
done -
无限循环
while true; do
循环体
done
until false; do
循环体
done
实战脚本:
1.
#Description: 扫描/etc/passwd文件每一行,如发现GECOS字段为空,则填充用户名和单位电话为62985600,并提示该用户的GECOS信息修改成功 #**************************************************** GECOS=" " while read line;do username=`echo $line|cut -d: -f1` GECOS=`echo $line| cut -d: -f5` if [ -z "$GECOS" ];then usermod -c "$username#62985600" $username &>/dev/null echo "usermod $username over!!!" else echo "$uaername GECOS is exies~~~" fi done < /etc/passwd
2.chmod -rw /tmp/file1,编写脚本/root/bin/per.sh,判断当前用户对/tmp/fiile1文件 是否不可读且不可写
#!/bin/bash FileName=/tmp/file1 [ ! -e $FileName ] && echo "file $FileName is no exits" && exit 2 #chmod -rw $FileName &>/dev/null [ -r $FileName -a -w $FileName ] && echo "the file is read and write for one user" || echo "the file is no read and no write for one user"
3、写一个脚本/root/bin/createuser.sh,实现如下功能:使用一个用户名做为参数,如果指定参数的用户存在,就显示其存在,否则添加之;显示添加的用户的id号等信息
#!/bin/bash read -p "enter a username:" input id -u $input &>/dev/null if [ $? -eq 0 ] ;then echo "user $input UID is exits" else echo "user $input is no exits,will useradd $input" useradd $input echo "useradd $input in over!!!" echo "user $input `id $input` " fi
4、写一个脚本/root/bin/yesorno.sh,提示用户输入yes或no,并判断用户输入的是yes还是no,或是其它信息
read -p "pleae enter (yes|no|other):" input if [ "$input" == "yes" ];then echo "user input a yes" elif [ "$input" == "no" ];then echo "user input a no" elif [ "$input" == "other" ];then echo "user input a other" fi ####################################### case $input in [yY][eE][sS]|[yY]) echo " user enter input is yes" ;; [Nn][oO]|[nN]) echo " user enter input is no" ;; [oO][tT]|[oO]) echo " user enter input is other" ;; *) exit 2 ;; esac
5、写一个脚本/root/bin/filetype.sh,判断用户输入文件路径,显示其文件类型(普通,目录,链接,其它文件类型)
read -p "please enter a filedir: " input if [ -f $input ];then echo "the file is a general file" elif [ -d $input ];then echo "the file is a directory" elif [ -h $input ];then echo "the file is a lianjie file" elif [ -b $input ];then echo "the file is a kuaishebei file" elif [ -p $input ];then echo "the file is taojie fiel" fi"
6、写一个脚本/root/bin/checkint.sh,判断用户输入的参数是否为正整数
read -p "please enter a num(int):" int if [ $int -le 0 &>/dev/null ];then echo "please enter a positive number!!" exit 2 else expr $int + 0 &>/dev/null if [ $? -eq 0 ];then echo "user enter a num is int num " else echo " user enter a num is no int number" fi fi
7、判断/var/目录下所有文件的类型
DirName=/var/ filename=`ls -p $DirName` for line in $filename do if [ -f $DirName$line ] ;then echo " $line is a file" elif [ -d $DirName$line ];then echo " $line is a dirstry" fi done
8、 添加10个用户user1-user10,密码同用户名
addnum=[1..10] for i in $addnum; do id user$i &>/dev/null if [ $? -ne 0 ];then useradd user$i |passwd --stdin &>/dev/nul echo "the user$i useradd over!" else echo "Error:the user user$i exits! read -p "dell exit user ?(yes|y| no)" inpu if [ $inpu == y ];then userdel -r user$i &>/dev/null echo "del user$i over!" useradd user$i |passwd --stdin &>/dev/nul echo "the user$i always useradd over!" else exit 7 fi fi done
9、 /etc/rc.d/rc3.d目录下分别有多个以K开头和以S开头的文件;分别读取每个文件,以K开头的文件输出为文件加stop,以S开头的文件输出为文件名加start;
“ K34filename stop”
“S66filename start”
dirname=/etc/rc.d/rc3.d/ dir=`ls $dirname` for i in $dir do alpha=`echo $i| grep -o "^[[:alpha:]]"` [ $alpha == "K" ] && echo "$i stop" [ $alpha == "S" ] && echo "$i start" done
10、写一个脚本,提示输入正整数n的值,计算1+2+3+…n的
总和
read -p "please enter a int number(n>0 ):" input [ -z $input -a $input -lt 0 ] && echo " num is lt 0 , again enter gt 0 !" && exit 2 sum=0 for i in `seq 1 $input` do sum=$[$sum+$i ] done echo "1 to N has sum is: $sum"
11、 写一个脚本,提示请输入网络地址,如192.168.0.0,判断输入的网段中主机在线状态
#!/bin/bash ip=10.1.252. i=0 up=0 down=0 while [ $i -le 255 ] do ping -c1 -w1 $ip$i &>/dev/null if [ $? -eq 0 ];then echo -e " $ip$i host is \033[32mup\033[0m " up=$[$up+1] else echo -e "$ip$i host is \033[31mdown\033[0m " down=$[$down+1] fi let i++; done echo " up:$up dowm:$down"
12、 打印九九乘法表
for i in {1..9} do for j in $(seq 1 $i) do echo -n -e "${i}x${j}=$[$i*$j]\t" done echo done
13、求100以内所有正整数之和
#1/bin/bash i=0 s=0 while [ $i != 100 ] do i=$[ $i+1 ] sum=$[ $sum+$i ] done echo $sum ############################## sum1=0 for ((i=0;i<=100;i++)) do sum1=$[$sum1+$i] done echo $sum1
14、通过ping命令探测172.16.250.1-254范围内的所有主机的在线状态,统计在线主机和离线主机各多少。
15、while循环打印九九乘法表
i=1 j=1 while [ $i -le 9 ] do while [ $j -le $i ] do echo -n -e "${i}x${j}=$[$i*$j]\t" let j++ done j=1 echo let i++; done
16、利用变量RANDOM生成10个随机数字,输出这个10数字,并显示其中的最大者和最小者
## i=0 max=0 min=100 while [ $i -lt 9 ] do num=`echo $[RANDOM%100]` echo $num [ $min -gt $num ] && min=$num [ $max -lt $num ] && max=$num let i++ done echo "big:$max smail:$min " unset i unset max unset min
17、打印国际象棋棋盘
############################################################方法一 #!/bin/bash read -p "please enter a hang num:" hang read -p "please enter a list num:" list i=1 j=1 b="\033[40m \033[0m" w="\033[47m \033[0m" sum="" while [ $i -le $hang ] do while [ $j -le $list ] do if [ $[$i%2] -gt 0 ];then [ $[$j%2] -eq 0 ] && sum=${sum}$b || sum=${sum}$w else [ $[$j%2] -gt 0 ] && sum=${sum}$b || sum=${sum}$w fi let j++ done echo -e "$sum" let i++ j=1 sum="" done ###########################################################方法二 #!/bin/bash read -p " please enter a num(int): " LIE read -p " please enter a num(int:)" HANG a="\033[43m \033[0m" b="\033[40m \033[0m" JSH(){ for((i=1;i<=${LIE};i++)){ [ $[$i%2] -eq 0 ] && echo -ne "$b" || echo -ne "$a" [ $i -eq ${LIE} ] && echo } } OSH(){ for((j=1;j<=${LIE};j++)){ [ $[$j%2] -eq 1 ] && echo -ne "$b" || echo -ne "$a" [ $j -eq ${LIE} ] && echo } } for ((h=1;h<=$HANG;h++)){ [ $[$h%2] -eq 1 ] && JSH || OSH } #####################################################方法三 #!/bin/bash i=1 while [ $i -le 8 ];do j=1 while [ $j -le 8 ];do sum=`expr $i + $j` z=`expr $sum % 2` [ $z -eq 0 ] && echo -ne "\033[41;1m \033[0m"||echo -ne "\033[43;1m \033[0m" let j++ done echo let i++ done
18.每隔3秒钟到系统上获取已经登录的用户的信息;如果发现用户hacker登录,则将登录时间和主机记录于日志/var/log/login.log中,并提示该用户退出系统。
#!/bin/bash clear username=wen while true do echo "3 min scan user login news" sleep 1 echo -e "当前系统的用户登录信息:\n `who`" name=`who| grep "$username"` &>/dev/null if [ $? -eq 0 ];then echo "发现$username用户登录,已记录该用户登录信息" $name >> /var/log/login.log echo " jilu over exit....." break else echo "the $username is no login" fi done
19.随机生成10以内的数字,实现猜字游戏,提示比较大或小,相等则退出
#!/bin/bash suiji=$[$RANDOM%10] read -p " please enter a number:" shuru until [[ $suiji -eq $shuru ]]; do #statements [ $shuru -lt $suiji ] && echo " $shuru is to smail" [ $shuru -gt $suiji ] && echo "$shuru is to big" read -p "please enter a number:" shuru done echo "$shuru is == RANDOM, exit"
20.使用until循环
#!/bin/bash i=1 until [ $i -gt 10 ] do echo $i let i++ [ $i -eq 5 ]&& exit echo ++++++++ done echo xxx
21.使用while循环打印三角
[root@wen-7 shangkelianxi]# bash whilesanjiao.sh plesae a nun :6 * *** ***** ******* ********* *********** [root@wen-7 shangkelianxi]# vim whilesanjiao.sh #!/bin/bash read -p "plesae a nun :" lie for i in `seq $lie` do for j in `seq $[ $lie-$i ]` do echo -n " " done for x in `seq $[ $[$i*2]-1]` do echo -n "*" done echo done
原创文章,作者:wencx,如若转载,请注明出处:http://www.178linux.com/37224