shell脚本编程2
今天继续学习了shell脚本编程,续之前写的脚本编程1。上次主要学了编程的基础,脚本格式,变量类型及变量的使用,条件测试,数字运算并且进行了部分练习,因为这部分逻辑思维能力要求不是很高,因此记忆起来难度不是特别大。
从今天开始便进入了流程控制以及函数、数组、高级字符串操作、高级变量等内容的学习,总体来说难度和重要程度都有很大的提升。
一、杂项知识整理
1、在条件判断的时候,如果有-a和-o存在,两端的比较使用的括号要用[]而不要用[[]]。在使用[[]]和[]时候注意,[]也支持扩展正则表达式,而[[]]只支持正则表达式。例如:
#!/bin/bash #test 2 # read -p "Please input yes or no: " ANSWER if [ "$ANSWER" == "yes" ] || [ "$ANSWER" == "YES" ];then echo "Your answer is yes!" elif [ "$ANSWER" == "no" -o "$ANSWER" == "NO" ];then echo "Your answer is no!" else echo "Please input a right answer!" fi
2、
[root@localhost shelltest]# ax=25 [root@localhost shelltest]# b=20 [root@localhost shelltest]# echo $ax$b 2520
3、source和bash以及.符号的区别:
source . 两者可以视作作用等效。通常用于重新执行刚修改的的初始化文档,影响当前的shell进程环境。source是内置命令,从c shell而来,点符号,从bourne shell而来。
sh/bash 打开新的子shell,读取并执行Filename中的命令,不影响当前的shell环境,该文件可以没有执行权限,bash命令是用bash环境来运行,*sh可以用自己的sh类型运行。
二、命令详解及事例
1、seq命令:print a sequence of numbers产生两个数之间的所有整数;
-s 指定分隔符,默认是回车
-f 指定格式
-w 指定输出数字同宽,不能跟-f一起用
步进
[root@localhost shelltest]# seq 2 5 2 3 4 5 [root@localhost shelltest]# seq 1 2 5 1 3 5 [root@localhost shelltest]# seq -s + 1 100 1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17+18+19+20+21+22+23+24+25+26+27+28+29+30+31+32+33+34+35+36+37+38+3 9+40+41+42+43+44+45+46+47+48+49+50+51+52+53+54+55+56+57+58+59+60+61+62+63+64+65+66+67+68+69+70+71+72+73+74+75+76+77+78+79+80+81+82+83+84+85+86+87+88+89+90+91+92+93+94+95+96+97+98+99+100
2、if语句:可以嵌套:
单分支:
if 判断条件;then
条件为真的分支
fi
多分支:
if 判断条件;then
if true
elif 判断条件;then
if true
else
all false
fi
3、条件判断:case语句
case 变量引用 in
PAT)
分支1
;;
PAT)
分支2
;;
*)
默认分支
;;
esac
注意:case支持glob风格的通配符
* 任意长度的任意字符
? 任意单个字符
[] 指定范围内的任意单个字符
a|b a或b
#!/bin/bash #answer yes or no # read -p "Please input your anwser ,yes or no: " ANS case $ANS in [yY][Ee][Ss]|Y|y) echo "Your answer is $ANS" ;; [nN][Oo]|n|N) echo "Your answer is $ANS" ;; *) echo "error answer" ;; esac
4、for循环:
for 变量名 in 列表;do
循环体
done
执行机制:一次将列表中的元素赋值给变量名;每次赋值后即执行一次循环体;直到列表中的元素耗尽,循环结束。
列表生成方式:(1)直接给出列表
(2)整数列表:(a){start..end} (b)$(seq[#1 步进] #2)若步进为1可省略,起始也可省略。
(3)返回列表的命令:$(COMMAND)
(4)使用glob,如*.sh
(5)变量引用:$@看作不同个变量 $*看作一个整体
5、while循环:
while CONDITION;do
循环体
done
CONDITION:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件为“true”,则执行一次循环;知道条件测试状态为“false”终止循环。
因此,CONDITION一般应该有循环控制变狼;而此变量的值会在循环体不断地被修正。
进入条件:CONDITION为真。退出条件:CONDITION为假。
6、until循环:until CONDITION;do
循环体
done
进入条件和退出条件与while相反。
7、循环控制语句:continue;break
continue:提前结束第n层的循环,直接进入新一轮的循环,即结束当前循环,开始新一轮循环
break:结束循环体,执行done或循环命令后的命令;exit停止脚本执行,break为停止循环
关于无限循环:while true;do
循环体
done
until false;do
循环体
done
三、作业及练习
1、判断用户输入的参数是否为正整数:正整数不包括0:第一个数可以为0例如002、032等,第二个数之后可有可无也可以是0,[[]]只支持正则表达式,* 匹配其前面的字符任意次。
#!/bin/bash #test 4 # read -p "Please input a number: " NUM if [[ "$NUM" =~ ^0*[1-9][0-9]*$ ]];then echo "It is a positive integer." else echo "It is not a positive integer." fi
2、使用一个用户名作为参数,如果指定参数的用户存在,就显示其存在,否则添加之,显示添加的用户的id号等信息:
#!/bin/bash #test 1 # read -p "Please input a username: " NAME if cut -d: -f1 /etc/passwd | grep "$NAME" &> /dev/null; then echo "username had been added!" else useradd $NAME echo "id $NAME" fi
3、判断用户输入文件路径,显示其文件类型。把L或者h放在判断普通文件f的前面,f判断链接文件的时候,会认做普通文件。
#!/bin/bash #Des:judge the type of a file #test 3 read -p "Please input the of a file: " PATH1 if [ -L "$PATH1" ];then echo "It is a flat file!" elif [ -d "$PATH1" ];then echo "It is a dir file!" elif [ -f "$PATH1" ];then echo "It is a link file!" else echo "other file!" fi
#!/bin/bash #filetype # read -p "Please input a path of a file: " PATH1 file $PATH
4、每隔3秒钟到系统上获取已经登录的用户的信息;如果发现用户hacker登录,则将登录时间和主机记录于日志/var/log/login.log中,并提示该用户退出系统。
#!/bin/bash #silence pavilion #test4 until false;do if w | grep "^hacker" &> /dev/null;then echo `w | grep "^hacker"` >> /tmp/log/login.log echo "logout now!" | write hacker fi sleep 3 done
5、随机生成10以内的数字,实现猜字游戏,提示比较大小,相等则退出。
#!/bin/bash #test 5 #num game # until false; do read -p "Please input a number between 0 and 10: " NUM RAN=$[RANDOM%10] if [[ "$RAN" -lt "$NUM" ]];then echo "Your number bigger!" continue fi if [[ "$RAN" -gt "$NUM" ]];then echo "Your number smaller!" continue fi if [[ "$RAN" -eq "$NUM" ]];then echo "You win!!" exit 2 fi done
6、编写脚本。求100以内所有正整数之和
#!/bin/bash #test 6 #silence pavilion # SUM=0 read -p "Please input a number: " NUM until [ "$NUM" -eq 0 ];do SUM=$[$NUM+$SUM] let NUM-- done echo "SUM=$SUM"
7、编写脚本,通过ping命令探测172.16.250.1-254范围内的所有主机在线状态,统计在线主机和离线主机各多少。
#!/bin/bash #name:pinguntil.sh #Des:ping #Author:Silence Pavilion #Version:1.0 #Usage:pinguntil.sh PING=1 NUMUP=0 NUMDOWN=0 until [ $PING = 255 ];do if ping -c 1 -w 2 172.16.250.$PING &> /dev/null;then echo "up" let NUMUP++ else echo "down" let NUMDOWN++ fi let PING++ done echo "UP:$NUMUP DOWN:$NUMDOWN"
8、编写脚本打印九九乘法表
#!/bin/bash #test 8 #nine nine until # I=1 J=1 until [ "$I" == 10 ];do J=1 until [ "$J" -gt "$I" ];do echo -ne "$J*$I=$[$I*$J]\t" J=$[$J+1] done I=$[$I+1] echo done echo
9、编写脚本,利用变量RANDOM生成10个随机数字,输出这10个数字并显示其中最大者和最小者
#!/bin/bash #random 10 #test 9 # I=1 MAX=$RANDOM echo $MAX MIN=$MAX until [ "$I" == 9 ];do NUM=`echo $RANDOM` echo $NUM if [[ "$MAX" -le "$NUM" ]];then MAX=$NUM fi if [[ "$MIN" -ge "$NUM" ]];then MIN=$NUM fi let I++ done echo MAX=$MAX echo MIN=$MIN
10、编写脚本,实现打印国际象棋棋盘。
#!/bin/bash #test 10 #chess #silence pavilion # I=1 J=1 until [ "$I" == 9 ];do echo -ne "$I" J=1 until [[ "$J" == 9 ]];do SUM=$[$I+$J] if [ "$[SUM%2]" -eq 0 ];then echo -ne "\033[43m \033[0m" else echo -ne "\033[45m \033[0m" fi let J++ done echo let I++ done echo " `echo {A..H}`"
11、打印等腰三角形
#!/bin/bash #triangle #test 11 #version 1.3 read -p "Please input a width: " WID WIDTH1=WID-1 NUM=1 NUM1=1 NUM2=$[2*$WID-1] NUM3=1 while [[ "$NUM" -le "$WID" ]];do NUM1=1 NUM3=1 while [[ "$NUM1" -le "$[$WID-$NUM]" ]]; do echo -n " " let NUM1++ done while [[ "NUM3" -le "$[2*$NUM-1]" ]]; do echo -n "*" let NUM3++ done echo let NUM++ done
原创文章,作者:SilencePavilion,如若转载,请注明出处:http://www.178linux.com/34240