linux之基础shell脚本编程2 if语句循环判断
本章命令:if case while for unit break continue
4.4.4 组合测试
第一种方式
COMMAND1 && COMMAND2 并且
COMMADN1 || COMMAND2 或者
!COMMAND 非
第二种方式
EXPRESSION1 -a EXPRESSION2 并且
EXPRESSION1 -o EXPRESSION2 或者
!EXPRESSION 非
必须使用测试命令进行
[ -z "$HOSTNAME" -o $HOSTNAME == "localhost.localdomain" ] && hostname www.liuyuworld.com ### 判断hostname是否为空或者hostname是"localhost.localdomain" 如果前面有一个条件成立,然后执行hostname 命令
[ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab ##判断文件是否存在并且可执行
实战训练4
1、chmod -rw /tmp/file1,编写脚本/root/bin/per.sh,判断当前用户对/tmp/fiile1文件 是否不可读且不可写
#!/bin/bash [ ! -r /tmp/file1 ] && [ ! -w /tmp/file1 ] && echo "不可读写" || echo "可读写"
[root@centos7 shell]# chmod -rw /tmp/file1 [root@centos7 shell]# ll /tmp/file1 ----------. 1 root root 0 Aug 10 16:22 /tmp/file1 [root@centos7 shell]# bash per.sh 可读写 [root@centos7 shell]# su cent [cent@centos7 shell]$ bash per.sh 不可读写
2、编写脚本/root/bin/nologin.sh和login.sh,实现禁止和充许普通用户登录系统
思路:当/etc/目录下存在 nologin 文件时,普通用户会无法登陆,因此,我们只需要通过删除或增加该文件来限制普通用户是否可登陆
[root@centos7 shell]# cat login.sh nologin.sh #!/bin/bash [ -e /etc/nologin ] && echo "`rm -f /etc/nologin` enable user login " #!/bin/bash [ -a /etc/nologin ] || touch /etc/nologin echo "disable user login "
执行 bash nologin.sh 脚本时,登陆普通用户会提示
Connecting to 172.18.16.152:22... Connection established. To escape to local shell, press 'Ctrl+Alt+]'. Connection closed by foreign host. Disconnected from remote host(centos7) at 20:11:18.
然后执行bash login.sh 脚本时,就可以直接登陆了
Connecting to 172.18.16.152:22... Connection established. To escape to local shell, press 'Ctrl+Alt+]'. Last failed login: Fri Aug 12 20:11:09 CST 2016 from 172.18.16.171 on ssh:notty There was 1 failed login attempt since the last successful login. Last login: Fri Aug 12 20:10:29 2016 from 172.18.16.171
五,流程控制
5.1 使用read命令来接受输入
使用read来把输入值分配给一个或多个shell变量:
-p :指定要显示的提示
-t :TIMEOUT
比如:
read -p "print a filename:" file
注意:read 从标准输入中读取值,给每一个单词分配一个变量,所有剩余单词都被分配给最后一个变量
5.2 条件选择if语句
if语句是选择执行,并且可以嵌套执行
单分支:
if 判断条件 ; then
条件为真的分支代码
fi
if [ $1 -gt 60 ];then echo "the grade is pass" fi
双分支:
if 判断条件 ; then
条件为真的分支代码
else
条件为假的分支代码
fi
if [ $1 -gt 60 ];then echo "the grade is pass" else echo "the grade is not pass" fi
多分支:
逐条件进行判断,第一次遇为“真”条件时,执行其分支,而后结束整个if语句
if CONDITION1; then if-true elif CONDITION2; then if-ture elif CONDITION3; then if-ture ... else all-false fi
5.3 条件判断case语句
case 变量引用 in
PAT1)
分支1
;;
PAT2)
分支2
;;
...
*)
默认分支
;;
esac
case支持glob风格的通配符:
*: 任意长度任意字符
?: 任意单个字符
[]:指定范围内的任意单个字符
a|b: a或b
实战训练5
1、写一个脚本/root/bin/createuser.sh,实现如下功能: 使用一个用户名做为参数,如果指定参数的用户存在,就显示其存在,否则添加之;显示添加的用户的id号等信息
##方法一 [root@centos7 test]# cat createuser.sh #!/bin/bash id $1 &>/dev/null && (echo '该用户已存在,信息为:' ; id $1) || ( useradd $1 ; echo '添加成功,信息为:' ; id $1) [root@centos7 test]# bash createuser.sh user01 添加成功,信息为: uid=1005(user01) gid=1005(user01) groups=1005(user01) [root@centos7 test]# bash createuser.sh user01 该用户已存在,信息为: uid=1005(user01) gid=1005(user01) groups=1005(user01)
##方法二 #!/bin/bash if id $1 &> /dev/null ; then echo "$1 is exsit,the info is `id $1`" else useradd $1 && echo "useradd is successful ,the info is `id $1`" fi
2、写一个脚本/root/bin/yesorno.sh,提示用户输入yes或 no,并判断用户输入的是yes还是no,或是其它信息
#!/bin/bash read -p "please input 'yes' or 'no' : " string case $string in [Yy][Ee][sS]|Y|y) echo "you input is yes" ;; [Nn][oO]|N|n) echo "you input is no" ;; *) echo "you input is other info" ;; esac
3、写一个脚本/root/bin/filetype.sh,判断用户输入文件路径,显示其文件类型(普通,目录,链接,其它文件类型)
#!/bin/bash read -p "please input a path of the file :" files if [ -b $files ];then echo "该文件是块设备" elif [ -c $files ] ;then echo "该文件是字符设备" elif [ -f $files ];then echo "该文件是普通文件" elif [ -h $files ];then echo "该文件是符号链接文件" elif [ -p $files ];then echo "该文件是管道文件" elif [ -S $files ];then echo "该文件是套接字文件" elif [ -d $files ];then echo "该文件是目录文件" else echo "文件或目录不存在" fi
4、写一个脚本/root/bin/checkint.sh,判断用户输入的参数是否为正整数
#!/bin/bash read -p "please input :" arg if [[ $arg =~ ^[[:digit:]]+$ ]] && [ $(expr $arg + 0) != 0 ] ;then echo "是正整数" else echo "不是正整数" fi
六,循环
循环执行:
将某代码重复运行多次
重复运行多次
循环次数事先已知
循环次数事先未知
有进入条件和退出条件
for,while,until
6.1
for循环
for 变量名 in 列表;do
循环体
done
执行机制:依次将列表中的元素赋值给"变量名";每次赋值后即执行一次循环体,直到类表中的元素耗尽,循环结束
列表生成方式:
(1) 直接给出列表
(2) 整数列表:
(a) {start..end}
(b) $(seq [start [step]] end)
(3) 返回列表的命令 $(COMMAND)
(4) 使用glob,如:*.sh
(5) 变量引用: $@, $*
实战训练6
要求:用for实现
1、判断/var/目录下所有文件的类型
#!/bin/bash for i in /var/* ;do if [ -b $i ];then echo "$i是块设备" elif [ -c $i ] ;then echo "$i是字符设备" elif [ -f $i ];then echo "$i是普通文件" elif [ -h $i ];then echo "$i是符号链接文件" elif [ -p $i ];then echo "$i是管道文件" elif [ -S $i ];then echo "$i是套接字文件" elif [ -d $i ];then echo "$i是目录文件" else echo "文件或目录不存在" fi done
2、添加10个用户user1-user10,密码同用户名
#!/bin/bash #添加10个用户 for i in user{1..10} ;do id $i &> /dev/null && echo "$i 用户已存在"|| (adduser $i ;echo "$i 用户添加成功") echo $i:$i | chpasswd done
#!/bin/bash #删除10个用户 for i in user{1..10} ;do id $i &> /dev/null && (userdel -fr $i ;echo "$i 删除成功") || echo "$i 删除失败,该用户肯不存在" done
3、/etc/rc.d/rc3.d目录下分别有多个以K开头和以S开头的 文件;分别读取每个文件,以K开头的文件输出为文件加stop ,以S开头的文件输出为文件名加start; “K34filename stop” “S66filename start”
#!/bin/bash for i in /etc/rc.d/rc3.d/[SK]* ;do if [ $(basename $i | cut -c1) == "K" ] ;then echo "`basename $i` stop" else echo "`basename $i` start" fi done
4、写一个脚本,提示输入正整数n的值,计算1+2+3+…n的 总和
#!/bin/bash read -p "please input a number:" n sum=0 for i in $(seq 1 $n);do let sum+=$i done echo "the sum is $sum"
5、写一个脚本,提示请输入网络地址,如192.168.0.0,判 断输入的网段中主机在线状态
#!/bin/bash file=`mktemp /tmp/pingip.XXXXXX` read -p "请输入网络地址 :" ip i=`echo $ip | cut -d'.' -f1-3` for z in {1..255};do { ip=$i.$z ping -c1 -W1 $ip &> /dev/null && (echo "$ip is up" ) && echo ip >> $file }& done sleep 1 echo "`cat $file | wc -l`在线" rm -f $file &> /dev/null
6、打印九九乘法表
#!/bin/bash for i in {1..9};do for j in $(seq 1 $i) ;do echo -ne "${j}x${i}=$[i*j]\t" done echo done
6.2
while 循环
语法:
while CONDITION; do
循环体
done
CONDITION:循环控制条件;进入循环之前,先做一次判 断;每一次循环之后会再次做判断;条件为“true”,则执行 一次循环;直到条件测试状态为“false”终止循环
因此:CONDTION一般应该有循环控制变量;而此变量的值会在循环体不断地被修正
进入条件:CONDITION为true
退出条件:CONDITION为false
实战训练7
要求:用while实现
1、求100以内所有正整数之和
#!/bin/bash sum=0 i=0 while [ $i -le 100 ] ;do let sum+=$i let i++ done echo $sum
2、通过ping命令探测172.16.250.1-254范围内的所有主机的在线状态,统计在线主机和离线主机各多少。
#!/bin/bash ip=10.1.250. i=1 sum=0 while [ $i -lt 255 ] ;do if ping -c1 -W1 $ip$i &> /dev/null ;then let sum+=1 echo "$ip$i is up" else echo "$ip$i is down" fi let i+=1 done echo "在线主机$sum台,离线$[255-sum]主机台"
3、打印九九乘法表
#!/bin/bash i=1 j=1 while [ $i -le 9 ] ;do while [ $j -le $i ] ;do echo -ne "${j}x${i}=$[i*j]\t" let j+=1 done let i+=1 j=1 echo done
4、利用变量RANDOM生成10个随机数字,输出这个10数字 ,并显示其中的最大者和最小者
#!/bin/bash let i=0,min=max=$RANDOM echo "$min " while [ $i -lt 9 ];do ran=$RANDOM echo "$ran " if [ $ran -ge $max ];then let max=ran fi if [ $ran -le $min ];then let min=ran fi let i+=1 done echo "最大值是 $max ,最小值是 $min"
5、打印国际象棋棋盘
#!/bin/bash let x=y=1 h=8 while [ $x -le $h ];do while [ $y -le $h ];do if [ $[(x+y)%2] -eq 0 ] ;then echo -en "\033[47m \033[0m" else echo -en "\033[40m \033[0m" fi let y+=1 done echo let x+=1,y=1 done
#!/bin/bash num=8 for((i=1;i<=$num;i++)){ for ((j=1;j<=$num;j++)) { if [ $[(i+j)%2] -eq 0 ];then echo -en "\033[47m \033[0m" else echo -en "\033[42m \033[0m" fi } echo }
6.3
until循环 (和while循环执行条件相反)
until CONDITION; do
循环体
done
进入条件: CONDITION 为false
退出条件: CONDITION 为true
6.4
循环控制语句continue,break
用于循环体中
continue [N]:提前结束第N层的本轮循环,而直接进入下一 轮判断;最内层为第1层
while CONDTIITON1; do CMD1 ... if CONDITION2; then continue fi CMDn ... done
break [N]:提前结束第N层循环,最内层为第1层
while CONDTIITON1; do CMD1 ... if CONDITION2; then break fi CMDn ... done
比如无限循环:
while true; do 循环体 done until false; do 循环体 Done
实战训练8
1、每隔3秒钟到系统上获取已经登录的用户的信息;如果发 现用户hacker登录,则将登录时间和主机记录于日志 /var/log/login.log中,并提示该用户退出系统
#!/bin/bash username=cent { while true ;do if who | egrep "^\b$username\b" &> /dev/null ;then who | egrep "^\b$username\b" >> /var/log/login.log echo "$username 已经登录" echo "fuck ,go out my system" | write $username else echo "$username 已经下线" fi sleep 3 done }
#!/bin/bash username=hacker exituser() { echo "fuck you,you will exit,haha" | write $username sleep 2 pidlist=$(ps -f h -u $username | tr -s ' '|cut -d' ' -f2) for i in $pidlist ;do kill -9 $i # echo "正在结束进程" done } while true ;do if w | egrep "^\b$username\b" &> /dev/null ;then w | egrep "^\b$username\b" >> /var/login.log echo "$username 已经登录" exituser else echo "$username 已经下线" fi sleep 3 done
2、随机生成10以内的数字,实现猜字游戏,提示比较大或小 ,相等则退出
#!bin/bash lim=10 let key=$RANDOM%lim read -p "please input a number less than $lim: " num until false;do if [ $num -le $lim &> /dev/null ] && [ $num -ge 0 &> /dev/null ] ;then if [ $num -lt $key ];then read -p "is small,please input again: " num elif [ $num -gt $key ];then read -p "is big,please input again: " num else echo "you are right,you are very clever" break fi else read -p "error,please input a number less than ten: " num fi done
6.5 一些特殊用法
while循环的特殊用法(遍历文件的每一行):
while read line; do
循环体
done < /PATH/FROM/SOMEFILE
依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将行赋值给变量line
练习 扫描/etc/passwd文件每一行,如发现GECOS字段为空,则填充用户名和单位电话为62985600,并提示该用户的GECOS信息修改成功。
#!/bin/bash phone=" phone number is 62985600" pathname=/etc/passwd while read line;do name=`echo $line|cut -d: -f1` b=`echo $line | cut -d: -f5|wc -c` if [ $b -eq 1 ] ;then chfn -f $name -p $phone $name &>/dev/null && echo "$name信息修改成功" || echo "$name信息修改失败" fi done < $pathname
双小括号方法,即((…))格式,也可以用于算术运算
双小括号方法也可以使bash Shell实现C语言风格的变量操作 #I=10 #((I++))
for循环的特殊格式:
for ((控制变量初始化;条件判断表达式;控制变量的修正表达式)) do
循环体
done
控制变量初始化:仅在运行到循环代码段时执行一次
控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算 ,而后再做条件判断
6.6 select 循环与菜单
select variable in list
do
循环体命令
done
select 循环主要用于创建菜单,按数字顺序排列的菜单项将显示在标准错误上,并显示PS3提示符等待用户输入
用户输入菜单列表中的某个数字,执行相应的命令
用户输入被保存在内置变量REPLY中
select是个无限循环,因此要记住用break命令退出循环,或用exit命令终止脚本,也可以按Ctrl+c退出循环
select经常和case联合使用
与for循环类似,可以省略in list,此时使用位置参数
比如
#!/bin/bash PS3="please input your chose:" list="start stop restart status exit" select k in $list do case $k in start) echo start ;; stop) echo stop ;; restart) echo restart ;; status) echo status ;; exit) echo exit ;; *) break ;; esac done
本章命令:if case while for unit break continue
linux之基础shell脚本编程4 字符串操作,变量赋值,配置用户环境
4.4.4 组合测试
第一种方式
COMMAND1 && COMMAND2 并且
COMMADN1 || COMMAND2 或者
!COMMAND 非
第二种方式
EXPRESSION1 -a EXPRESSION2 并且
EXPRESSION1 -o EXPRESSION2 或者
!EXPRESSION 非
必须使用测试命令进行
[ -z "$HOSTNAME" -o $HOSTNAME == "localhost.localdomain" ] && hostname www.liuyuworld.com ### 判断hostname是否为空或者hostname是"localhost.localdomain" 如果前面有一个条件成立,然后执行hostname 命令
[ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab ##判断文件是否存在并且可执行
实战训练4
1、chmod -rw /tmp/file1,编写脚本/root/bin/per.sh,判断当前用户对/tmp/fiile1文件 是否不可读且不可写
#!/bin/bash [ ! -r /tmp/file1 ] && [ ! -w /tmp/file1 ] && echo "不可读写" || echo "可读写"
[root@centos7 shell]# chmod -rw /tmp/file1 [root@centos7 shell]# ll /tmp/file1 ----------. 1 root root 0 Aug 10 16:22 /tmp/file1 [root@centos7 shell]# bash per.sh 可读写 [root@centos7 shell]# su cent [cent@centos7 shell]$ bash per.sh 不可读写
2、编写脚本/root/bin/nologin.sh和login.sh,实现禁止和充许普通用户登录系统
思路:当/etc/目录下存在 nologin 文件时,普通用户会无法登陆,因此,我们只需要通过删除或增加该文件来限制普通用户是否可登陆
[root@centos7 shell]# cat login.sh nologin.sh #!/bin/bash [ -e /etc/nologin ] && echo "`rm -f /etc/nologin` enable user login " #!/bin/bash [ -a /etc/nologin ] || touch /etc/nologin echo "disable user login "
执行 bash nologin.sh 脚本时,登陆普通用户会提示
Connecting to 172.18.16.152:22... Connection established. To escape to local shell, press 'Ctrl+Alt+]'. Connection closed by foreign host. Disconnected from remote host(centos7) at 20:11:18.
然后执行bash login.sh 脚本时,就可以直接登陆了
Connecting to 172.18.16.152:22... Connection established. To escape to local shell, press 'Ctrl+Alt+]'. Last failed login: Fri Aug 12 20:11:09 CST 2016 from 172.18.16.171 on ssh:notty There was 1 failed login attempt since the last successful login. Last login: Fri Aug 12 20:10:29 2016 from 172.18.16.171
五,流程控制
5.1 使用read命令来接受输入
使用read来把输入值分配给一个或多个shell变量:
-p :指定要显示的提示
-t :TIMEOUT
比如:
read -p "print a filename:" file
注意:read 从标准输入中读取值,给每一个单词分配一个变量,所有剩余单词都被分配给最后一个变量
5.2 条件选择if语句
if语句是选择执行,并且可以嵌套执行
单分支:
if 判断条件 ; then
条件为真的分支代码
fi
if [ $1 -gt 60 ];then echo "the grade is pass" fi
双分支:
if 判断条件 ; then
条件为真的分支代码
else
条件为假的分支代码
fi
if [ $1 -gt 60 ];then echo "the grade is pass" else echo "the grade is not pass" fi
多分支:
逐条件进行判断,第一次遇为“真”条件时,执行其分支,而后结束整个if语句
if CONDITION1; then if-true elif CONDITION2; then if-ture elif CONDITION3; then if-ture ... else all-false fi
5.3 条件判断case语句
case 变量引用 in
PAT1)
分支1
;;
PAT2)
分支2
;;
...
*)
默认分支
;;
esac
case支持glob风格的通配符:
*: 任意长度任意字符
?: 任意单个字符
[]:指定范围内的任意单个字符
a|b: a或b
实战训练5
1、写一个脚本/root/bin/createuser.sh,实现如下功能: 使用一个用户名做为参数,如果指定参数的用户存在,就显示其存在,否则添加之;显示添加的用户的id号等信息
##方法一 [root@centos7 test]# cat createuser.sh #!/bin/bash id $1 &>/dev/null && (echo '该用户已存在,信息为:' ; id $1) || ( useradd $1 ; echo '添加成功,信息为:' ; id $1) [root@centos7 test]# bash createuser.sh user01 添加成功,信息为: uid=1005(user01) gid=1005(user01) groups=1005(user01) [root@centos7 test]# bash createuser.sh user01 该用户已存在,信息为: uid=1005(user01) gid=1005(user01) groups=1005(user01)
##方法二 #!/bin/bash if id $1 &> /dev/null ; then echo "$1 is exsit,the info is `id $1`" else useradd $1 && echo "useradd is successful ,the info is `id $1`" fi
2、写一个脚本/root/bin/yesorno.sh,提示用户输入yes或 no,并判断用户输入的是yes还是no,或是其它信息
#!/bin/bash read -p "please input 'yes' or 'no' : " string case $string in [Yy][Ee][sS]|Y|y) echo "you input is yes" ;; [Nn][oO]|N|n) echo "you input is no" ;; *) echo "you input is other info" ;; esac
3、写一个脚本/root/bin/filetype.sh,判断用户输入文件路径,显示其文件类型(普通,目录,链接,其它文件类型)
#!/bin/bash read -p "please input a path of the file :" files if [ -b $files ];then echo "该文件是块设备" elif [ -c $files ] ;then echo "该文件是字符设备" elif [ -f $files ];then echo "该文件是普通文件" elif [ -h $files ];then echo "该文件是符号链接文件" elif [ -p $files ];then echo "该文件是管道文件" elif [ -S $files ];then echo "该文件是套接字文件" elif [ -d $files ];then echo "该文件是目录文件" else echo "文件或目录不存在" fi
4、写一个脚本/root/bin/checkint.sh,判断用户输入的参数是否为正整数
#!/bin/bash read -p "please input :" arg if [[ $arg =~ ^[[:digit:]]+$ ]] && [ $(expr $arg + 0) != 0 ] ;then echo "是正整数" else echo "不是正整数" fi
六,循环
循环执行:
将某代码重复运行多次
重复运行多次
循环次数事先已知
循环次数事先未知
有进入条件和退出条件
for,while,until
6.1
for循环
for 变量名 in 列表;do
循环体
done
执行机制:依次将列表中的元素赋值给"变量名";每次赋值后即执行一次循环体,直到类表中的元素耗尽,循环结束
列表生成方式:
(1) 直接给出列表
(2) 整数列表:
(a) {start..end}
(b) $(seq [start [step]] end)
(3) 返回列表的命令 $(COMMAND)
(4) 使用glob,如:*.sh
(5) 变量引用: $@, $*
实战训练6
要求:用for实现
1、判断/var/目录下所有文件的类型
#!/bin/bash for i in /var/* ;do if [ -b $i ];then echo "$i是块设备" elif [ -c $i ] ;then echo "$i是字符设备" elif [ -f $i ];then echo "$i是普通文件" elif [ -h $i ];then echo "$i是符号链接文件" elif [ -p $i ];then echo "$i是管道文件" elif [ -S $i ];then echo "$i是套接字文件" elif [ -d $i ];then echo "$i是目录文件" else echo "文件或目录不存在" fi done
2、添加10个用户user1-user10,密码同用户名
#!/bin/bash #添加10个用户 for i in user{1..10} ;do id $i &> /dev/null && echo "$i 用户已存在"|| (adduser $i ;echo "$i 用户添加成功") echo $i:$i | chpasswd done
#!/bin/bash #删除10个用户 for i in user{1..10} ;do id $i &> /dev/null && (userdel -fr $i ;echo "$i 删除成功") || echo "$i 删除失败,该用户肯不存在" done
3、/etc/rc.d/rc3.d目录下分别有多个以K开头和以S开头的 文件;分别读取每个文件,以K开头的文件输出为文件加stop ,以S开头的文件输出为文件名加start; “K34filename stop” “S66filename start”
#!/bin/bash for i in /etc/rc.d/rc3.d/[SK]* ;do if [ $(basename $i | cut -c1) == "K" ] ;then echo "`basename $i` stop" else echo "`basename $i` start" fi done
4、写一个脚本,提示输入正整数n的值,计算1+2+3+…n的 总和
#!/bin/bash read -p "please input a number:" n sum=0 for i in $(seq 1 $n);do let sum+=$i done echo "the sum is $sum"
5、写一个脚本,提示请输入网络地址,如192.168.0.0,判 断输入的网段中主机在线状态
#!/bin/bash file=`mktemp /tmp/pingip.XXXXXX` read -p "请输入网络地址 :" ip i=`echo $ip | cut -d'.' -f1-3` for z in {1..255};do { ip=$i.$z ping -c1 -W1 $ip &> /dev/null && (echo "$ip is up" ) && echo ip >> $file }& done sleep 1 echo "`cat $file | wc -l`在线" rm -f $file &> /dev/null
6、打印九九乘法表
#!/bin/bash for i in {1..9};do for j in $(seq 1 $i) ;do echo -ne "${j}x${i}=$[i*j]\t" done echo done
6.2
while 循环
语法:
while CONDITION; do
循环体
done
CONDITION:循环控制条件;进入循环之前,先做一次判 断;每一次循环之后会再次做判断;条件为“true”,则执行 一次循环;直到条件测试状态为“false”终止循环
因此:CONDTION一般应该有循环控制变量;而此变量的值会在循环体不断地被修正
进入条件:CONDITION为true
退出条件:CONDITION为false
实战训练7
要求:用while实现
1、求100以内所有正整数之和
#!/bin/bash sum=0 i=0 while [ $i -le 100 ] ;do let sum+=$i let i++ done echo $sum
2、通过ping命令探测172.16.250.1-254范围内的所有主机的在线状态,统计在线主机和离线主机各多少。
#!/bin/bash ip=10.1.250. i=1 sum=0 while [ $i -lt 255 ] ;do if ping -c1 -W1 $ip$i &> /dev/null ;then let sum+=1 echo "$ip$i is up" else echo "$ip$i is down" fi let i+=1 done echo "在线主机$sum台,离线$[255-sum]主机台"
3、打印九九乘法表
#!/bin/bash i=1 j=1 while [ $i -le 9 ] ;do while [ $j -le $i ] ;do echo -ne "${j}x${i}=$[i*j]\t" let j+=1 done let i+=1 j=1 echo done
4、利用变量RANDOM生成10个随机数字,输出这个10数字 ,并显示其中的最大者和最小者
#!/bin/bash let i=0,min=max=$RANDOM echo "$min " while [ $i -lt 9 ];do ran=$RANDOM echo "$ran " if [ $ran -ge $max ];then let max=ran fi if [ $ran -le $min ];then let min=ran fi let i+=1 done echo "最大值是 $max ,最小值是 $min"
5、打印国际象棋棋盘
#!/bin/bash let x=y=1 h=8 while [ $x -le $h ];do while [ $y -le $h ];do if [ $[(x+y)%2] -eq 0 ] ;then echo -en "\033[47m \033[0m" else echo -en "\033[40m \033[0m" fi let y+=1 done echo let x+=1,y=1 done
#!/bin/bash num=8 for((i=1;i<=$num;i++)){ for ((j=1;j<=$num;j++)) { if [ $[(i+j)%2] -eq 0 ];then echo -en "\033[47m \033[0m" else echo -en "\033[42m \033[0m" fi } echo }
6.3
until循环 (和while循环执行条件相反)
until CONDITION; do
循环体
done
进入条件: CONDITION 为false
退出条件: CONDITION 为true
6.4
循环控制语句continue,break
用于循环体中
continue [N]:提前结束第N层的本轮循环,而直接进入下一 轮判断;最内层为第1层
while CONDTIITON1; do CMD1 ... if CONDITION2; then continue fi CMDn ... done
break [N]:提前结束第N层循环,最内层为第1层
while CONDTIITON1; do CMD1 ... if CONDITION2; then break fi CMDn ... done
比如无限循环:
while true; do 循环体 done until false; do 循环体 Done
实战训练8
1、每隔3秒钟到系统上获取已经登录的用户的信息;如果发 现用户hacker登录,则将登录时间和主机记录于日志 /var/log/login.log中,并提示该用户退出系统
#!/bin/bash username=cent { while true ;do if who | egrep "^\b$username\b" &> /dev/null ;then who | egrep "^\b$username\b" >> /var/log/login.log echo "$username 已经登录" echo "fuck ,go out my system" | write $username else echo "$username 已经下线" fi sleep 3 done }
#!/bin/bash username=hacker exituser() { echo "fuck you,you will exit,haha" | write $username sleep 2 pidlist=$(ps -f h -u $username | tr -s ' '|cut -d' ' -f2) for i in $pidlist ;do kill -9 $i # echo "正在结束进程" done } while true ;do if w | egrep "^\b$username\b" &> /dev/null ;then w | egrep "^\b$username\b" >> /var/login.log echo "$username 已经登录" exituser else echo "$username 已经下线" fi sleep 3 done
2、随机生成10以内的数字,实现猜字游戏,提示比较大或小 ,相等则退出
#!bin/bash lim=10 let key=$RANDOM%lim read -p "please input a number less than $lim: " num until false;do if [ $num -le $lim &> /dev/null ] && [ $num -ge 0 &> /dev/null ] ;then if [ $num -lt $key ];then read -p "is small,please input again: " num elif [ $num -gt $key ];then read -p "is big,please input again: " num else echo "you are right,you are very clever" break fi else read -p "error,please input a number less than ten: " num fi done
6.5 一些特殊用法
while循环的特殊用法(遍历文件的每一行):
while read line; do
循环体
done < /PATH/FROM/SOMEFILE
依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将行赋值给变量line
练习 扫描/etc/passwd文件每一行,如发现GECOS字段为空,则填充用户名和单位电话为62985600,并提示该用户的GECOS信息修改成功。
#!/bin/bash phone=" phone number is 62985600" pathname=/etc/passwd while read line;do name=`echo $line|cut -d: -f1` b=`echo $line | cut -d: -f5|wc -c` if [ $b -eq 1 ] ;then chfn -f $name -p $phone $name &>/dev/null && echo "$name信息修改成功" || echo "$name信息修改失败" fi done < $pathname
双小括号方法,即((…))格式,也可以用于算术运算
双小括号方法也可以使bash Shell实现C语言风格的变量操作 #I=10 #((I++))
for循环的特殊格式:
for ((控制变量初始化;条件判断表达式;控制变量的修正表达式)) do
循环体
done
控制变量初始化:仅在运行到循环代码段时执行一次
控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算 ,而后再做条件判断
6.6 select 循环与菜单
select variable in list
do
循环体命令
done
select 循环主要用于创建菜单,按数字顺序排列的菜单项将显示在标准错误上,并显示PS3提示符等待用户输入
用户输入菜单列表中的某个数字,执行相应的命令
用户输入被保存在内置变量REPLY中
select是个无限循环,因此要记住用break命令退出循环,或用exit命令终止脚本,也可以按Ctrl+c退出循环
select经常和case联合使用
与for循环类似,可以省略in list,此时使用位置参数
比如
#!/bin/bash PS3="please input your chose:" list="start stop restart status exit" select k in $list do case $k in start) echo start ;; stop) echo stop ;; restart) echo restart ;; status) echo status ;; exit) echo exit ;; *) break ;; esac done
更多推荐
所有评论(0)