case语句
case语句为多选择语句。可以用case语句匹配一个值与一个模式,如果匹配成功,执行相 匹配的命令。
case var in 定义变量 pattern 1) 模式1; 用 | 分割多个模式,相当于or command1 需要执行的语句 ;; 两个分号代表命令结束 pattern 2) command2 ;; pattern 3) command3 ;; *) default,不满足以上模式,默认执行*)下面的语句 command4 ;; esac esac表示case语句结束
示例1:
当给程序传入start、stop、reload三个不同参数时分别执行相应命令。
#!/bin/bash case $1 in start|S) echo "service is running..." ;; stop|P) echo "service is stoped." ;; reload|R) echo "service is reloading..." ;; *) echo "usage:$0 start|stop|reload..." ;; esac
示例2:
模拟一个多任务维护界面。当执行某程序时先显示总菜单,然后进行相应选择后进入子菜单。
#!/bin/bash echo "**************************" echo "******欢迎进入总菜单******" echo " 操作类型 " echo " 1——系统 " echo " 2——程序 " echo " 3——数据库 " echo " 0——退出 " echo "**************************" read -p "请选择操作类型:" choose echo case "$choose" in 0) echo "谢谢使用,如有问题联系管理员:root@localhost" ;; 1) echo "欢迎进入红帽子系统" ;; 2) echo "程序维护" ;; 3) clear echo "*******欢迎来到子菜单*****" echo "**********操作类型********" echo " 1——备份 " echo " 2——维护 " echo " 3——优化 " echo " 0——退出 " echo "**************************" read -p "请选择操作类型:" choose1 case "$choose1" in 1) echo backup ;; 0) echo "谢谢使用!" ;; *) echo "请选择操作类型" ;; esac ;; *) echo "how are you?" ;; esac
函数
shell中允许将一组命令集合或语句形成一段可用代码,这些代码块称为shell函数。给这段代码起个名字称为函数名,后续可以直接调用该段代码。
语法结构: function_name() { command command } function function_name() { command command } 函数名() { ...... } function 函数名() { ....... command1 command2 } 函数中return说明: 1.return可以结束一个函数,类似于前面讲的循环控制语句break(结束当前循环,执行循环体后面的代码) 2.return默认返回函数中最后一个命令的退出状态,也可以给定参数值,该参数值的范围是0-256之间。 3.如果没有return命令,函数将返回最后一个Shell的退出值。
函数的调用
当前命令行调用
[root@server shell03]# cat fun1.sh #!/bin/bash hello(){ echo welcome to itcast return 1 echo skdfjkdjf } function world(){ echo wa hahaha } [root@server shell03]# source fun1.sh //读取函数定义文件 [root@server shell03]# hello welcome to itcast [root@server shell03]# world wa hahaha
定义到用户的环境变量中
[stu1@server ~]$ cat .bashrc # .bashrc # Source global definitions if [ -f /etc/bashrc ]; then . /etc/bashrc fi source /tmp/fun1.sh # User specific aliases and functions 或者 # .bashrc # Source global definitions if [ -f /etc/bashrc ]; then . /etc/bashrc fi # User specific aliases and functions hello (){ echo welcome to itcast }
脚本中调用
#!/bin/bash hello(){ echo 888888 } case $1 in start|S) hello echo "service is running..." ;; stop|P) echo "service is stoped." ;; reload|R) hello;echo "service is reloading..." ;; *) echo "usage:$0 start|stop|reload..." ;; esac 或者 source /xxxx/fun1.sh ...
应用案例
需求:写一个脚本让用户输入基本信息(姓名,性别,年龄),如不输入一直提示输入,最后根据用户的信息输出相对应的内容
思路:
-
循环直到输入字符串不为空
-
根据用户输入信息做出匹配判断
#!/bin/bash input_fun() { input_var="" output_var=$1 while [ -z $input_var ] do read -p "$output_var" input_var done echo $input_var } name=$(input_fun "Input your name:") sex=$(input_fun "Input your sex(男or女):") age=$(input_fun "Input your age:") case $sex in 男|man) if [ $age -ge 20 -a $age -le 35 ];then echo "$name先生,你好帅" elif [ $age -gt 35 ];then echo "$name大叔,你油腻了吗?" else echo "$name小伙子,前途无量" fi ;; 女|lady|woman) echo "$name小姐姐你好漂亮" ;; *) echo "你是泰国来的吗?" ;; esac
应用案例二
-
输入一个等级(A-E),查看每个等级的成绩;如:输入A,则显示“90分~100分”,依次类推
-
模拟2人第一次相亲的场景,使用read让用户输入它的名字,性别,年龄(年龄放在性别判断后);在case里面再嵌套case菜单,使之选项更丰富。
要求:
1)
-
对性别进行判断,如果不输入男或者女,则显示”你是泰国来的吗?“
-
如果是男的,对其年龄进行判断。
2)
-
如果男的年龄大于等于18岁则显示“某某先生,你结婚了吗?”;
-
如果对方回答结了或者yes,则显示“结了你来这凑什么热闹”;
-
如果对方回答没有或者no,再次询问“那你有房有车吗?”;
-
如果既不说结了也不说没结则显示:“你Y的到底结没结婚啊?”
-
如果回答有房有车,则显示”咱去民政局领证吧“;
-
如果回答没有,则显示“不好意思,我去下洗手间。”;
-
如果既不说有又不说没有,则显示“别浪费时间,请正面回答”。
-
如果男的年龄小于18岁,则显示“某某某你个小毛孩也来这凑热闹啦”
3)如果是女的,并且年龄大于等于18岁,则显示”某某女士你好“;否则显示”某某小姐你好“
参考: #!/bin/bash read -p "输入你的姓名:" name read -p "输入你的性别:" gender case "$gender" in 男|man|male|boy ) read -p "输入你的年龄:" age if [ $age -ge 18 ];then read -p "$name先生,你结婚了吗?" anwser case "$anwser" in 结了|有|yes ) echo "结了你还来干嘛?" ;; 没结|没有|没|no ) read -p "有房有车吗?" anwser2 case "$anwser2" in 有) echo "咱就直接去民政局领证吧" ;; 没有 ) echo "不好意思,我去下洗手间" ;; * ) echo "别浪费时间,请正面回答" esac ;; * ) echo "你到底结没结?" esac else echo "$name小子" fi ;; 女|woman|female|girl|lady ) read -p "输入你的年龄:" age if [ $age -ge 18 ];then echo "$name女士" else echo "$name小姐" fi ;; * ) echo "你是泰国来的吗?" esac 该程序有个bug:如果输入年龄为负数或者0也是可以的,如何修复bug?增加一个条件:如果输入的年龄小于等于10则显示:”不跟你玩了。。。“ 在最后加入如下语句即可: if [ $age -ge 18 ];then echo "$name女士" elif [ $age -le 10 ];then echo "不跟你玩了" exit 1 else echo "$name小姐" fi ;; * ) echo "你是泰国来的吗?" esac
正则表达式
什么是正则表达式
正则表达式(Regular Expression、regex或regexp,缩写为RE),也译为正规表示法、常规表示法,是一种字符模式,用于在查找过程中匹配指定的字符。
许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。
正则表达式这个概念最初是由Unix中的工具软件(例如sed和grep)普及开的。
支持正则表达式的程序如:locate |find| vim| grep| sed |awk
第一类正则
元字符:指那些在正则表达式中具有特殊意义的专用字符,如:点(.) 星(*) 问号(?)等
前导字符:即位于元字符前面的字符
常用元字符
(1). 任意单个字符,除了换行符 (2)* 前导字符出现0次或连续多次 ab*能匹配“a”,“ab”以及“abb”,但是不匹配“cb” (3).* 任意长度的字符 (4)^ 行的开头 (5)$ 行的结尾 (6)^$ 空行 (7)[ ] 匹配指定字符组内的任一字符 (8) [^] 匹配不在指定字符组内的任一字符 (9)^[] 匹配以指定字符组内的任一字符开头 (10)^[^] 匹配不以指定字符组内的任一字符开头 (11)< 取单词的头 (12)> 取单词的尾 (13)<> 精确匹配符号 (14){n} 匹配前导字符连续出现n次 (15){n,} 匹配前导字符至少出现n次 (16){n,m} 匹配前导字符出现n次与m次之间 (17) (xxx) 保存被匹配的字符 将192.168.0.254 换成 192.168.1.254 vim 1.txt :%s#(192.168).0.(254)#1.100.2 //底行模式下匹配 # sed -n 's#(192.168).0.254#1.1.254#p' 找出含有192.168的行,同时保留192.168并标记为标签1,之后可以使用1来引用它。最多可以定义9个标签,从左边开始编号,最左边的是第一个。 将helloworld yourself 换成hellolilei myself vim 1.txt :%s#(hello)world your(self)#1lilei my2#g # sed -n 's/(hello)world your(self)/1lilei my2/p' 1.txt hellolilei myself [0-9] [a-z] [A-Z] [a-zA-Z] [a-Z] =================================================================================== Perl内置正则: d 匹配数字 [0-9] w 匹配字母数字下划线[a-zA-Z0-9_] s 匹配空格、制表符、换页符[ ] #grep -P 'd' test.txt #grep -P 'w' test.txt #grep -P 's' test.txt
扩展类的正则表达式 grep -E 或则 egerp
扩展正则表达式元字符 + 匹配一个或多个前导字符 ? 匹配零个或一个前导字符 a|b 匹配a或b () 组字符 hello myself yourself (my|your)self x{m} 前导字符x重复m次 x{m,} 前导字符x重复至少m次 x{m,n} 前导字符x重复m到n次 # grep "root|ftp|adm" /etc/passwd # egrep "root|ftp|adm" /etc/passwd # grep -E "root|ftp|adm" /etc/passwd # grep -E 'o+gle' test.txt # grep -E 'o?gle' test.txt # egrep 'go{2,}' 1.txt # egrep '(my|your)self' 1.txt [root@server shell03]# grep -E '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}' 1.txt 10.1.1.1 [root@server shell03]# grep -E '([0-9]{1,3}.){3}[0-9]{1,3}' 1.txt 10.1.1.1 [root@server shell03]# grep -P 'd+.d+.d+.d+' 1.txt 10.1.1.1 [root@server shell03]# grep -P '(d+.){3}d+' 1.txt 10.1.1.1 [root@server shell03]# grep -P '(d+.)+d+' 1.txt 10.1.1.1 [root@server shell03]# grep -P '(d+.){3}d+' 1.txt 10.1.1.1 [root@server shell03]# grep -P '(d{1,3}.){3}d+' 1.txt 10.1.1.1
第二类正则
表达式 功能 示例 [:alnum:] 字母与数字字符 [[:alnum:]]+ [:alpha:] 字母字符(包括大小写字母) [[:alpha:]]{4} [:blank:] 空格与制表符 [[:blank:]]* [:digit:] 数字字母 [[:digit:]]? [:lower:] 小写字母 [[:lower:]]{4,} [:upper:] 大写字母 [[:upper:]]+ [:punct:] 标点符号 [[:punct:]] [:space:] 包括换行符,回车等在内的所有空白 [[:space:]]+
案例
#!/bin/bash conf=/etc/httpd/conf/httpd.conf input_fun() { input_var="" output_var=$1 while [ -z $input_var ] do read -p "$output_var" input_var done echo $input_var } ipaddr=$(input_fun "Input Host ip[192.168.0.1]:") web_host_name=$(input_fun "Input VirtualHostName [www.test.cc]:") root_dir=$(input_fun "Input host Documentroot dir:[/var/www/html]:") [ ! -d $root_dir ] && mkdir -p $root_dir chown apache.apache $root_dir && chmod 755 $root_dir echo this is $web_host_name > $root_dir/index.html echo "$ipaddr $web_host_name" >> /etc/hosts [ -f $conf ] && cat >> $conf <<end NameVirtualHost $ipaddr:80 <VirtualHost $ipaddr:80> ServerAdmin webmaster@$web_host_name DocumentRoot $root_dir ServerName $web_host_name ErrorLog logs/$web_host_name-error_log CustomLog logs/$web_host_name-access_loh common </VirtualHost> end