目录
使用结构化命令 for循环 while循环 until循环 break命令 continue命令
前言
>>>学习循环的目的:了解如何重复一些过程和命令,即为循环执行一组命令直到某个特定条件
>>>与循环相关的命令主要包括:for、while和until
①for循环
>>>bash shell提供了for命令,允许我们创建一个遍历一系列值的循环
>>>for循环便利的列表假定每个值都是用空格分割的,例如(1 "2" "贝")
>>>当某个值两边都是用了双引号时,shell不会将双引号当成值的一部分
for循环基本格式:
for val in list
do
commands
done
或者 for val in list;do commands;done (常用)
关于for循环基本格式说明:
>>>list参数,提供迭代要用到的一系列的值,可以是用空格隔开的字符串,也可以是产生值的命令
>>>for循坏结束后,变量val的值会保留最后一次赋予的值(变量在剩余shell脚本中依然生效)
只有unset 变量,变量才会被清空
[bei@localhost test]$ cat for.sh
#!/bin/bash
for val in 0 7 5
do
echo $val
done
echo "The last val:val=$val"
unset val
echo "After unset val:val=$val"
[bei@localhost test]$ bash for.sh
0
7
5
The last val:val=5
After unset val:val=
执行完for循环 ,val仍然保留最后一次赋予的值"5",并且在剩余shell脚本中仍然生效,
如果需要让变量val失效,用unset即可
>>>do和done之间可输入一条或多条shell命令,包括嵌套if语句
[bei@localhost test]$ cat for.sh
#!/bin/bash
count=1
for i in 59 60 99
do
if [ $i -ge 60 ] #在for循环里嵌套了if语句
then
echo "Grade $count : $i"
fi
count=$[$count+1]
done
[bei@localhost test]$ bash for.sh
Grade 2 : 60
Grade 3 : 99
读取值复杂的列表的内容
问题:遍历列表中的值,存在空格或特殊字符
方法:>>>使用 \ 处理
>>>使用双引号或单引号处理
案例
[bei@localhost test]$ cat for.sh
#!/bin/bash
for val in It's a lucky dog !
do
echo $val
done
[bei@localhost test]$ bash for.sh
for.sh: line 2: unexpected EOF while looking for matching `''
for.sh: line 6: syntax error: unexpected end of file
>>>列表中存在特殊字符,会报错
>>>解决方法1:使用\处理
[bei@localhost test]$ cat for.sh
#!/bin/bash
for val in It\'s a lucky dog \!
do
echo $val
done
[bei@localhost test]$ bash for.sh
It's
a
lucky
dog
!
>>>解决方法2:使用双引号或单引号处理(此方法不仅可以输出特殊字符,还可以输出存在空格的值)
>>>shell不会把最外层的引号当做值的一部分,里面的引号会被输出
[bei@localhost test]$ cat for.sh
#!/bin/bash
for val in "It's" a "lucky dog" "!"
do
echo $val
done
[bei@localhost test]$ bash for.sh
It's
a
lucky dog #使用引号输出含有空格的值
!
从变量读取列表:
>>>当列表较长,直接将列表放在for循环中,不美观,修改麻烦
>>>可以先将列表赋给某个变量,然后再去遍历变量中的值
案例:
[bei@localhost test]$ cat for.sh
#!/bin/bash
list="1 2 3 4 5" #将列表赋予变量,然后遍历变量中的值,实现从变量读取列表的值
list=$list" 6 7" #实现列表的拼接
for i in $list
do
echo $i
done
[bei@localhost test]$ bash for.sh
1
2
3
4
5
6
7
从命令读取值:
使用方法
>>>file="xxx.txt"
>>>for I in `cat $file` #使用反引从命令读取值
案例
[bei@localhost test]$ cat txt
Guangdong Guangzhou
Guangdong Shenzhen
Guangdong Shantou
[bei@localhost test]$ cat for.sh
#!/bin/bash
list="./txt"
for i in `cat $list`
do
echo $i
done
[bei@localhost test]$ bash for.sh
Guangdong
Guangzhou
Guangdong
Shenzhen
Guangdong
Shantou
更改字段分隔符:
>>>上一个案例,从命令读取值时,txt文件中的内容,行中存在空格,一行中的内容会被分别输出,不会在同一行输出
可以通过修改分隔符的方式解决这个问题
什么是分隔符
>>>分隔符全称叫内部字段分隔符(internal field separator)
>>>通过环境变量IFS,定义了bash shell字段分隔符的一系列字符
set |grep IFS
IFS=$' \t\n'
>>>默认情况下bash shell的字段分隔符:
空格( )
制表符(\t)
换行符(\n)
>>>如何修改分隔符——可在shell脚本中临时修改IFS环境变量
[bei@localhost test]$ cat txt
Guangdong Guangzhou
Guangdong Shenzhen
Guangdong Shantou
[bei@localhost test]$ cat for.sh
#!/bin/bash
IFS_old=$IFS
IFS=$'\n'
file='txt'
for i in `cat $file`
do
echo "$i"
done
IFS=$IFS_old
[bei@localhost test]$ bash for.sh
Guangdong Guangzhou
Guangdong Shenzhen
Guangdong Shantou
>>>当需要在脚本中临时修改IFS变量时,需要先将IFS的默认值保存,当临时IFS变量使用完后,再讲IFS恢复成默认值
>>>指定多个分隔符:
IFS=$' \t\n:;"' #将空格,制表符,换行符,分号,和双引号作为分隔符
用通配符读取目录
使用通配符/var/history遍历这个目录,并对目录下的文件进行判断是否为普通文件
[bei@localhost test]$ cat for.sh
#!/bin/bash
for i in /var/history/*
do
if [ -f "$i" ]
then
echo "$i is exist and is a file"
else
echo "$i is exist and is not a file"
fi
done
[bei@localhost test]$ bash for.sh
/var/history/bei-507.log is exist and is a file
/var/history/root-0.log is exist and is a file
for循环实战——循环处理文件数据
结合的技术:
>>>使用嵌套循环
>>>修改IFS环境变量
案例:处理/etc/passwd文件中的数据,要求逐行遍历/etc/passwd文件,并将IFS变量的值修改成冒号
[bei@localhost test]$ cat loop.sh
#!/bin/bash
IFS_OLD=$IFS
IFS=$'\n'
for line in `cat /etc/passwd`
do
echo "Vales in $line"
IFS=:
for value in $line
do
echo "$value"
done
done
IFS=$IFS_OLD
[bei@localhost test]$ bash loop.sh
Vales in root:x:0:0:root:/root:/bin/bash
root
x
0
0
root
/root
/bin/bash
Vales in bin:x:1:1:bin:/bin:/sbin/nologin
bin
x
1
1
bin
/bin
/sbin/nologin
Vales in daemon:x:2:2:daemon:/sbin:/sbin/nologin
daemon
x
2
2
daemon
/sbin
/sbin/nologin
......
②while循环
>>>可以简单理解,while命令是if-then语句和for循环的混杂体
>>>while命令允许我们定义一个要测试的命令,我们定义的命令若返回的退出状态码为0,就会循环执行一组命令
>>>只要测试条件中的退出状态码一直为0,while命令后面那部分代码就会一直执行,
直到测试条件中的test命令返回的退出状态码不为0,while命令就会终止执行命令
while循环的基本格式
while test command #测试命令退出状态码是0,就会去执行命令other commands
do
other commands
done
说明:
>>>while命令的关键是指定的test command返回的退出状态码要随着循环的执行而变化
>>>如果test command的退出状态码没有变化
若一直是0,则会产生一个死循环,other commands会一直被执行
若一直是非0,则other commands一直不会被执行
>>>可以在done后面追加[>> file],会将循环的结果输出重定向到某个文件
举例:
[bei@localhost test]$ cat ./txt
[bei@localhost test]$ cat while.sh
#!/bin/bash
val=1
while [ $val -le 3 ]
do
echo "$val"
val=$[ $val + 1 ]
done >> ./txt
[bei@localhost test]$ bash while.sh
[bei@localhost test]$ cat ./txt
1
2
3
当有多个测试条件时,以最后一个测试条件的退出状态码为准
while test command1
test command2
test command3
…….
done
说明
>>>此while循环以test command3的退出状态码为准
>>>test command1和test command2不会影响循环的跳转
③until循环
>>>until命令和while命令的工作方式,是完全相反的
>>>untile命令允许我们定义一个要测试的命令,我们定义的命令若返回的退出状态码为非0,就会循环执行一组命令
>>>只要测试条件中的退出状态码一直为非0,until命令后面那部分代码就会一直执行,
直到测试条件中的test命令返回的退出状态码为0,until命令就会终止执行命令
>>>通俗理解:直到until中的测试条件成立,until循环才会停止
untill循环的基本格式:
until test command #测试命令退出状态码是非0,就会去执行命令other commands
do
other commands
done
举例
[bei@localhost test]$ cat until.sh
#!/bin/bash
val=8
until [ $val -gt 10 ]
do
echo "$val"
val=$[ $val + 1 ]
done
[bei@localhost test]$ bash until.sh
8
9
10
说明:
当val=8时,test命令返回退出状态码为非0,until循环执行do后面的命令
当val=9时,test命令返回退出状态码为非0,until循环执行do后面的命令
当val=10时,test命令返回退出状态码为非0,until循环执行do后面的命令
当val=11时,test命令返回退出状态码为0,until循环不执行后面的命令,循环停止
循环嵌套
何为嵌套循环
>>>循环语句可以在循环内部使用任何类型的命令,当循环内使用的是其他循环命令时,这种称为嵌套循环
>>>嵌套层次越多,时间复杂度越大,一般来说时间复杂度是乘积关系
案例:
[bei@localhost test]$ cat nested.sh
#!/bin/bash
for (( a=1;a<4;a++ ))
do
echo "outside loop : $a"
for (( b=1;b<4;b++ ))
do
echo "inside loop : $b"
done
done
[bei@localhost test]$ bash nested.sh
outside loop : 1
inside loop : 1
inside loop : 2
inside loop : 3
outside loop : 2
inside loop : 1
inside loop : 2
inside loop : 3
outside loop : 3
inside loop : 1
inside loop : 2
inside loop : 3
案例:
[bei@localhost test]$ cat nested.sh
#!/bin/bash
a=1
while [ $a -le 3 ]
do
b=1
echo "ouside loop : $a"
until [ $b -ge 3 ]
do
echo " inside loop : $b"
b=$[$b+1]
done
a=$[$a+1]
done
[bei@localhost test]$ bash nested.sh
ouside loop : 1
inside loop : 1
inside loop : 2
ouside loop : 2
inside loop : 1
inside loop : 2
ouside loop : 3
inside loop : 1
inside loop : 2
④控制循环
>>>为何需要控制循环?
当循环启动时,在不对循环进行控制情况下,就必须等待循环迭代完成后循环才能终止
>>>如何控制循环?
两个命令可以帮我们控制循环内部的情况: break命令 和 continue命令
break命令
>>>退出进行中的循环(包括for循环,while循环和until循环)
案例
[bei@localhost test]$ cat break.sh
#!/bin/bash
for i in 1 2 3 4 5
do
if [ $i -le 3 ]
then
echo "$i"
else
echo "breaking"
break
fi
done
[bei@localhost test]$ bash break.sh
1
2
3
breaking
说明:在for循环,当满足if-then条件时,不执行break命令
当不满足条件时,执行break命令,跳出正在处理的循环,即for循环
>>>对于嵌套循环,只会跳出和break最接近的循环,不会跳出外面的循环
案例
[bei@localhost test]$ cat break.sh
#!/bin/bash
for((a=1;a<4;a++))
do
echo "a=$a"
for((b=1;b<4;b++))
do
if [ $b -lt 3 ]
then
echo " b=$b"
else
echo "breaking"
break
fi
done
done
[bei@localhost test]$ bash break.sh
a=1
b=1
b=2
breaking
a=2
b=1
b=2
breaking
a=3
b=1
b=2
breaking
说明:break命令只会跳出最接近它的那一层循环,而不会影响外部的循环
>>>对于嵌套循环,若需要停止外部循环,可以使用参数值 break n 即跳出n层循环
其中的n表示跳出循环的层级,默认情况下n的值为1,即为跳出当前循环
案例
[bei@localhost test]$ cat break.sh
#!/bin/bash
for((a=1;a<4;a++))
do
echo "a=$a"
for((b=1;b<4;b++))
do
if [ $b -lt 3 ]
then
echo " b=$b"
else
echo "breaking"
break 2
fi
done
done
[bei@localhost test]$ bash break.sh
a=1
b=1
b=2
breaking
说明:break命令的2意味着它是跳出两层循环,即外面那层循环也停止了
continue命令
>>>只会跳过这一次循环后面部分代码,但并不完全终止整个循环
案例
[bei@localhost test]$ cat continue.sh
#!/bin/bash
for((a=1;a<=2;a++))
do
echo "a=$a"
for((b=1;b<=3;b++))
do
if [ $b -ne 2 ]
then
echo " b=$b"
else
continue
echo "command1"
fi
echo "command2"
done
done
[bei@localhost test]$ bash continue.sh
a=1
b=1
command2
b=3
command2
a=2
b=1
command2
b=3
command2
说明:当b=1时,正常输出
当b=2时,执行continue命令,跳过这一次循环后面部分命令,包括command1和command2
但for循环未停止
当b=3时,由于循环未停止,正常输出
说明:
>>>以上内容是本人学习的总结
>>>如还有错误,请留言,指正
>>>亦可分享自己的想法,互相学习