一、循环语句
什么是循环语句?
实现重复计算和操作的语句。即解决循环问题的语句。许多高级语言中都有好几种循环语句。
一般均设置一个退出或进入循环的条件来控制循环的次数
bash中的循环控制语句:
for,while,until
1、for
for循环语法:w
for 变量名 in 列表
do
循环体 #do和循环体可以写在同一行,但减少可读性
done
for,do,done 加;分隔也可以写在同一行
进入条件:列表非空
退出条件:列表遍历结束
运行特性:
第一遍:将列表中的第一个元素赋值“变量名”定义的变量,而后执行完成循环体;
第二遍:、、、直到元素遍历结束,循环退出
列表的生成方式:
1、直接列出 如: stu100 stu101 stu102 或{stu100,stu101,stu102}
2、生成整数列表 如:{start_num..end_num} 例:{1..10} 特定格式,表示1到10
3、使用文件名通配的机制生成列表
4、使用命令的结果生成
seq LAST #从1开始,不是0
seq FIRST LAST
seq FIRST STEP LAST
[root@Node3 src]# cat
for i in {1..10}
do
echo $i
done
[root@Node3 src]# bash
1
2
3
4
5
6
7
8
9
10
[root@Node3 src]# for i in `seq 5`;do echo $i;done
1
2
3
4
5显示/etc/passwd文件中偶数行用户的用户名。
[root@Node3 src]# cat line=`cat /etc/passwd|wc -l` for i in `seq 2 2 $line` do echo `head -$i /etc/passwd|tail -1|cut -d: -f1` done [root@Node3 src]#
2、循环语句while,until
特别适用于循环次数未知的场景,
while
语法:
while CONDITION
do 循环体
控制变量的修正表达式
done
进入条件:当CONDITON为“真”
退出条件:当CONDITION为“假”
until
语法:
until CONDITION
do 循环体
控制变量的修正表达式
done
进入条件:当CONDITION为“假”时
退出条件:当CONDITION为“真”时
3、循环控制
continue [N]:提前结束本次循环,而直接进入下一轮
break [N]:提前结束循环
后面接数字N表示跳过或结束本循环和外面的父循环总共N个循环
4、死循环
语法1:
while true # 这里true写":"也可以
do 循环体
if CONDITION
then break
fi
done
语法2:
until false
do 循环体
if CONDITION
then break
fi
done
就是一直循环直到某个条件出现才结束咯
5、while、for的特殊用法
while循环的特殊用法:
遍历文件的每一行
语法:
while read VARIABLE
do 循环体
done < /FILENAME
for循环的特殊用法:
语法:
for ((expr1;expr2;expr3))
do 循环体
done
(()):C语言风格的for(())表达式;不支持-eq这类的运算符。不支持-a和-o,支持<=、>=、<、>这类比较符和&&、||
expr1:定义控制变量,并初始赋值
expr2:循环控制条件
expr3:修正控制变量
练习:
1、通过键盘提示用户输入字符,将用户输入的小写字母转换为大写,转换一次之后,再次提醒,再输入再转换,直到输入quit推出。
[root@Node3 ~]# cat read -p "Input a word : " word while [ "$word" != "quit" ] do echo $word|tr 'a-z' 'A-Z' read -p "Input a word again: " word done [root@Node3 ~]# bash Input a word : xj XJ Input a word again: 12 12 Input a word again: 1234 1234 Input a word again: adfs ADFS Input a word again: magedu MAGEDU Input a word again: quit
2、提示用户输入一个用户名,如果存在:显示该用户的UID和SHELL信息,否则,显示无此用户,提示用户再次输入,输入quit退出。
[root@Node3 ~]# cat read -p "Please input a username: " username while [ "$username" != "quit" ] do if [ -z "$username" ] then echo "username is null" elif grep -q "^$username\b" /etc/passwd then echo "`grep "^$username" /etc/passwd|cut -d: -f3,7`" else echo "no $username" fi read -p "Please input a username again: " username done [root@Node3 ~]# bash Please input a username: sb no sb Please input a username again: 1 2 no 1 2 Please input a username again: xj 500:/bin/bash Please input a username again: username is null Please input a username again: quit [root@Node3 ~]#
3、提供用户输入一个用户名,判断用户是否登录了当前系统,如果没有登录,则停止5s之后,再次判断,知道用户登录系统,显示“用户来了”而后退出
[root@Node3 ~]# cat read -p "Please a username: " username while [[ "$username" != quit ]] do if [ -z "$username" ] then echo "username is null" elif who|grep -q "^$username" then echo "$username login" break else sleep 5 fi done
4、写一个脚本,完成如下任务
1)提示用户输入一个磁盘设备文件路径;如果用户给定的路径文件不存在或不是一个块设备文件,则提示用户重新输入,知道输入正确为止,或者输入quit以9为退出码结束脚本
2)提示用户“下面的操作会清空磁盘中的数据,并提问是否继续”,如果用户给出字符y或单词yes,则继续,否则,则提供以8为退出码结束脚本
3)将用户指定的磁盘上的分区清空,而后创建两个主分区,大小分别为100M和512M
4)格式化此两个分区
5)将第一个分区挂载至/mnt/boot目录,第二个分区挂载至/mnt/sysroot目录
练习:
1、计算1到100之内正整数的和
for:
[root@Node3 ~]# declare -i sum=0;for i in {1..100};do sum+=i;done;echo $sum
5050while:
[root@Node3 ~]# declare -i sum=0;declare -i i=0;while [ $i -le 100 ];do sum+=$i;let i++;done;echo $sum 5050
until:
[root@Node3 ~]# declare -i sum=o;declare -i i=0;until [ $i -gt 100 ];do sum+=i;let i++;done;echo $sum 5050
2、求100以内偶数(奇数)之和
for:
[root@Node3 ~]# declare -i sum=0;for i in `seq 2 2 100`;do sum+=i;done;echo $sum 2550 [root@Node3 ~]# declare -i sum=0;for i in `seq 1 2 100`;do sum+=i;done;echo $sum 2500 [root@Node3 ~]# declare -i sum=0;declare -i i=0;for i in `seq 100`;do if [ $[i%2] -eq 0 ];then sum+=i;let i++;fi;done;echo $sum 2550 [root@Node3 ~]# declare -i sum=0;declare -i i=0;for i in `seq 100`;do if [ $[i%2] -eq 0 ];then continue;else sum+=i;let i++;fi;done;echo $sum 2500
while:
[root@Node3 ~]# declare -i sum=0;declare -i i=0;while [ $i -le 100 ];do sum+=i;i+=2;done;echo $sum 2550 [root@Node3 ~]# declare -i sum=0;declare -i i=1;while [ $i -le 100 ];do sum+=i;i+=2;done;echo $sum 2500
until:
[root@Node3 ~]# declare -i sum=0;declare -i i=0;until [ $i -gt 100 ];do if [ $[i%2] -eq 0 ];then sum+=i;fi;let i++;done;echo $sum 2550 [root@Node3 ~]# declare -i sum=0;declare -i i=0;until [ $i -gt 100 ];do if [ $[i%2] -ne 0 ];then sum+=i;fi;let i++;done;echo $sum 2500
3、打印九九乘法表
[root@Node3 ~]# declare -i i=0;declare -i j=0;for i in {1..9};do for j in `seq $i`;do echo -n "$j*$i=$[i*j] ";done;echo;done;
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81[root@Node3 ~]# cat declare -i i=1 declare -i j=1 while [ $i -le 9 ] do while [ $j -le $i ] do echo -n "$j*$i=$[i*j] " let j++ done echo let i++ j=1 #注意这里每次i循环要将j归1 done [root@Node3 ~]# bash 1*1=1 1*2=2 2*2=4 1*3=3 2*3=6 3*3=9 1*4=4 2*4=8 3*4=12 4*4=16 1*5=5 2*5=10 3*5=15 4*5=20 5*5=25 1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36 1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49 1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64 1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
例:
每隔3秒查看当前系统上是否有名为“gentoo”的用户登录
如果登录了,则显示gentoo已经登录;如果未登录就显示仍未登录,并显示这是第几次查看了
[root@BAIYU_110 shell]# cat #!/bin/bash # 用变量替换“gentoo”和相应的命令就可以实现服务或用户上线下线提醒 # declare -i i=0 while true;do if who|grep "gentoo" &>/dev/null;then echo "The gentoo is logged" break fi let i++ echo "$i gentoo is not login" sleep 3 done [root@BAIYU_110 shell]# bash 1 gentoo is not login 2 gentoo is not login 3 gentoo is not login 4 gentoo is not login 5 gentoo is not login 6 gentoo is not login 7 gentoo is not login 8 gentoo is not login ^C
例:找出UID为偶数的所有用户,显示其用户名和UID
[root@Node3 ~]# cat while read line do if [[ `echo $line|cut -d: -f3`%2 -eq 0 ]] then echo `echo $line|cut -d: -f1` fi done</etc/passwd [root@Node3 ~]# [root@BAIYU_110 shell]# cat #!/bin/bash # while read line;do userid=$(echo $line|cut -d: -f3) if [ $[$userid%2] -eq 0 ];then echo $line | cut -d: -f1,3 fi done</etc/passwd [root@BAIYU_110 shell]# bash root:0 daemon:2 mail:8 haldaemon:68 ntp:38 sshd:74 tcpdump:72 gentoo:500
例:求100以内所有正整数之和
[root@BAIYU_110 shell]# cat #!/bin/bash for ((i=1;i<=100;i++));do # 在这种特定格式下数字比较也可以直接使用<=号了 let sum+=$i done echo "The sum is $sum" [root@BAIYU_110 shell]# bash The sum is 5050 [root@Node3 ~]# declare -i sum=0;for ((i<=100));do sum+=i;let i++;done;echo $sum -bash: syntax error: arithmetic expression required -bash: syntax error: `((i<=100))' 0 [root@Node3 ~]# declare -i sum=0;for ((i<=100;));do sum+=i;let i++;done;echo $sum -bash: syntax error: arithmetic expression required -bash: syntax error: `((i<=100;))' 0 [root@Node3 ~]# declare -i sum=0;for ((i=0;i<=100));do sum+=i;let i++;done;echo $sum -bash: syntax error: arithmetic expression required -bash: syntax error: `((i=0;i<=100))' 0 [root@Node3 ~]# declare -i sum=0;for ((i=0;i<=100;));do sum+=i;let i++;done;echo $sum 5050 [root@Node3 ~]# declare -i sum=0;for ((i=0;i<=100;));do sum+=i;let i++;done;echo $sum 5050
while和until也可以使用类似的格式:
[root@Node3 ~]# declare -i sum=0;declare -i i=0;while ((i<=100));do sum+=i;let i++;done;echo $sum 5050 [root@Node3 ~]# declare -i sum=0;while ((i=0;i<=100;i++));do sum+=i;done;echo $sum #while和until不能像for一样在(( ))里面,修正变量 -bash: ((: i=0;i<=100;i++: syntax error: invalid arithmetic operator (error token is ";i<=100;i++") 0 [root@Node3 ~]# declare -i sum=0;declare -i i=0;until ((i>100));do sum+=i;let i++;done;echo $sum 5050
打印九九乘法表
[root@BAIYU_110 shell]# cat
#!/bin/bash
#
for ((x=1;x<=9;x++));do
for ((y=1;y<=$x;y++));do
echo -n -e "${y}x${x}=$[$y*$x]\t"
done
echo
done
[root@BAIYU_110 shell]# bash
1x1=1
1x2=2 2x2=4
1x3=3 2x3=6 3x3=9
1x4=4 2x4=8 3x4=12 4x4=16
1x5=5 2x5=10 3x5=15 4x5=20 5x5=25
1x6=6 2x6=12 3x6=18 4x6=24 5x6=30 6x6=36
1x7=7 2x7=14 3x7=21 4x7=28 5x7=35 6x7=42 7x7=49
1x8=8 2x8=16 3x8=24 4x8=32 5x8=40 6x8=48 7x8=56 8x8=64
1x9=9 2x9=18 3x9=27 4x9=36 5x9=45 6x9=54 7x9=63 8x9=72 9x9=81
[root@BAIYU_110 shell]#二、read和shift
1、read命令
read 是从输入文件或者标准输入中或cat等输出的信息中,每次读取一行进行处理。
read命令使用格式:
read [OPTIONS] VAR...
-p:输出一句话来当作提示
-t:等待多少秒后退出
-n:当接收的字符达到预定数目时,自动退出,并将输入的值赋值给变量
-s:隐藏输入数据,适用于机密信息的输入
[root@BAIYU_207 shell]# read -p "please enter yourname: " name please enter yourname: xxj [root@BAIYU_207 shell]# echo $name xxj [root@BAIYU_207 shell]# read -t 5 -p "please enter yourname: " name please enter yourname: [root@BAIYU_207 shell]# [root@BAIYU_207 shell]# echo $name [root@BAIYU_207 shell]# read -n 2 -p "please enter yourname: " name please enter yourname: xx[root@BAIYU_207 shell]# echo $name xx [root@BAIYU_207 shell]# read -s -p "please enter yourname: " name please enter yourname: [root@BAIYU_207 shell]# echo $name xxj
在read命令行中也可以不指定变量,如果不指定变量,那么read命令会将接收到的数据放置在环境变量REPLY中。
环境变量REPLY中包含输入的所有数据,可以像使用其他变量一样在shell脚本中使用环境变量REPLY.
[root@BAIYU_207 shell]# read -t 5 -p "please enter yourname: " please enter yourname: xxj [root@BAIYU_207 shell]# echo $REPLY xxj
在上面read后面的变量只有name一个,也可以有多个,这时如果输入多个数据,则第一个数据给第一个变量,第二个数据给第二个变量,如果输入数据个数过多,则最后所有的值都给最后一个变量。如果输入不够则后面的变量为空
[root@BAIYU_207 shell]# read -p "please enter yourname: " name1 name2 name3 please enter yourname: aa bb cc dd ee [root@BAIYU_207 shell]# echo $name1 aa [root@BAIYU_207 shell]# echo $name2 bb [root@BAIYU_207 shell]# echo $name3 cc dd ee
2、位置参数轮替(shift)
计算给定参数的和?
[root@Node3 ~]# cat declare -i sum=0 for i in `seq 1 $#` do let sum+=$1 shift done echo $sum [root@Node3 ~]# bash 1 2 3 6 [root@Node3 ~]# bash 2 4 6 12

















