一、介绍
shell脚本编程进阶主要包括流程控制,函数,数组,高级字符串操作和高级变量,在这里,主要介绍流程控制。
流程控制主要是过程式编程语言,分为顺序执行,选择执行和循环执行。
条件选择if语句
if语句分为单分支,双分支和多分支三种,单分支只需输入一段条件为真的分支代码即可,而双分支需要输入两段代码,一段条件为真,一段条件为假,多分支更复杂,逐条进行判断,第一次遇到真条件时,执行分支,然后fi结束整个if语句。
单分支: if 判断条件;then 条件为真的分支代码 fi 双分支: if 判断条件;then 条件为真的分支代码 else 条件为假的分支代码 fi fi
多分支: if 判断条件1;then 条件为真的分支代码 elif 判断条件2;then 条件为真的分支代码 elif 判断条件3;then 条件为真的分支代码 else 以上条件都为假的分支代码 fi
示例:
编辑脚本/root/bin/fi1.sh,实现如下功能:输入一个数字,当这个数字等于5时,输出middle,当这个数字大于等于0小于5时,输出small,当这个数字小于0时,输出error,否则,输出big。
#!/bin/bash if [ $1 -eq 5 ];then echo "middle" elif [ $1 -lt 5 -a $1 -ge 0 ];then echo "small" elif [ $1 -lt 0 ];then echo "error" else echo "big" fi
注:用【】进行条件判断时要注意前中后都有空格,脚本编写完成后不要忘了加执行权限,用.或source执行脚本。
2.条件判断case语句
case语句是先引用一个变量,之后把每个判断条件输入各个分支中,以esac为结尾。
case 变量引用 in PAT1) 分支1 ;; PAT2) 分支2 ;; ... *) 默认分支 ;; esac
注:case支持glob风格的通配符:
*: 任意长度任意字符 ?: 任意单个字符 []:指定范围内的任意单个字符 a|b: a或b
示例:
编辑脚本/root/bin/case1.sh,如果输入的是boy,m,ae,n,male,则输出 Gentleman,若是输入的是 girl,wom,ae,n,female,则输出Lady,否则,输出Error。
#!/bin/bash case $1 in boy|m[ae]n|male)echo "Gentleman";; girl|wom[ae]n|female)echo "Lady";; *)echo "Error";; esac
注:每行代码编写完成后不要忘了“;;”。
循环执行是比较重要的部分。循环执行就是将某代码段重复运行多次,有进入条件和退出条件。
3.for 循环
依次将列表中的元素赋值给“变量名”; 每次赋值后即执行一次循环体; 直到列表中的元素耗尽,循环结束
for 变量名 in 列表;do 循环体 done
列表生成方式:
(1) 直接给出列表
(2) 整数列表:
(a) {start..end}
(b) $(seq [start [step]] end)
(3) 返回列表的命令
$(COMMAND)
(4) 使用glob,如:*.sh
(5) 变量引用;
$@, $*
示例:
编辑脚本/root/bin/xin.sh,实现打印红心矩形
#!/bin/bash for i in {1..10};do for n in {1..10};do echo -en '\033[31m?\033[0m' done echo done
注:for循环可以套其他的循环,其他的循环也可以套for循环
4.while循环
while 循环控制条件;do 循环体 done
实验:把分区利用率大于10%的分区显示 sda5 will be full : 30%
#!/bin/bash df |grep sd |while read disk ;do diskname=$(echo $disk |cut -d' ' -f1) diskusage=$(echo $disk |sed -r 's/.* ([0-9]+)%.*/\1/') [ $diskusage -ge 10 ] && echo "$diskname will be full: ${diskusage}%" done
CONDITION:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件
为“true”,则执行一次循环;直到条件测试状态为“false”终止循环
CONDTION一般应该有循环控制变量;而此变量的值会在循环体不断地被修正
进入条件:CONDITION为true
退出条件:CONDITION为false
while CONDITION; do 循环体 done
5.循环控制语句continue
用于循环体中
continue [N]:提前结束第N层的本轮循环,而直接进入下一轮判断;最内层为第1层
while CONDTIITON1; do CMD1 ... if CONDITION2; then continue fi CMDn ... done
示例:
运用while循环输出1~9
while [ $n -lt 10 ];do echo $n let n++ if [ $n -eq 5 ];then continue fi done
6.循环控制语句break
用于循环体中
break [N]:提前结束第N层循环,最内层为第1层
while CONDTIITON1; do CMD1 ... if CONDITION2; then break fi CMDn ... done
7.until循环
进入条件: CONDITION 为false
退出条件: CONDITION 为true
until CONDITION; do 循环体 done
示例:
运用until循环输出1~09
until [ $n -eq 10 ];do echo $n let n++ done
注:until循环语句条件判断为假才能循环下去,跟while循环除了这个判断条件其他都一样。
8.循环控制语句shift
shift [n]
用于将参量列表 list 左移指定次数,缺省为左移一次。
参量列表 list 一旦被移动,最左端的那个参数就从列表中删除。while 循环
遍历位置参量列表时,常用到 shift
./doit.sh a b c d e f g h
示例:
doit.sh
#!/bin/bash # Name: doit.sh # Purpose: shift through command line arguments # Usage: doit.sh [args] while [ $# -gt 0 ] # or (( $# > 0 )) do echo $* shift done
9.特殊用法
while循环的特殊用法(遍历文件的每一行):
while read line; d 循环体 done < /PATH/FROM/SOMEFILE
依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将行赋值给变量line
示例:
while read userline;do userid=$(echo "$userline" |cut -d: -f3) username=$(echo "$userline" |cut -d: -f1) if [ "$userid" -lt 1000 ];then echo "$username is a sys user" else echo "$username is a comm user" fi done < /etc/passwd
二、练习
创建一个脚本名为useradd.sh,当执行-a选项时,会批量创建用户user1~user20,要求userX的uid为200x,userxx的uid为20xx,1~8用户的shell为/sbin/nologin,9~20用户的uid为/bin/bash。最后这20个用户的密码都设置为centos;当执行-d选项时,批量删除用户user1~user20。连同家目录一同删除。
查看用户账号:/etc/passwd
查看UID:/etc/group
查看密码:/etc/shadow
#!/bin/bash case $1 in -a)for n in {1..5} ;do if [ $n -le 2 ];then useradd -u $[2000+$n] -s /sbin/nologin user$n else useradd -u $(echo "2000+$n"|bc) user$n fi echo "centos" |passwd --stdin user$n &> /dev/null echo "user$n created" done;; -d)for n in {1..5} ;do userdel -r user$n done;; *)echo "Please type -a or -d";; esac