三、更多结构化命令
前面已经讲述了检查命令的输出和变量的值来操作shell脚本程序中的流。如下主要说明如何执行重复的过程和命令,使得一组命令循环下去,直到满足特定的条件。
知识内容:
# 使用for语句循环
# 使用until语句迭代
# 使用while语句
# 结合循环
# 重定向循环输出
1、for命令
重复一系列的命令是常见的编程实践,对于shell如处理目录下的所有文件、系统中的所有用户、或者文本文件中的所有行。对于bash
shell的for循环命令格式:
for xxx in xx
do
done
在xx参数里头提供一系列用户迭代的值,如下例:
1.1、读取列表中的值
#!/bin/bash
for test in CCNA CCNP RHCE OCP OCM
do
done
[root@wzp ~]# ./test3
the learning list is CCNA
the learning list is CCNP
the learning list is RHCE
the learning list is OCP
the learning list is OCM
[root@wzp
~]# cat test3
#!/bin/bash
for test in CCNA CCNP RHCE OCP OCM
do
done
echo the last list is $test
test='good job'
echo but the last point is $test
[root@wzp ~]# ./test3
the learning list is CCNA
the learning list is CCNP
the learning list is RHCE
the learning list is OCP
the learning list is OCM
the last list is OCM
but the last point is good job
1.2、读取列表中的复杂值
如果列表中出现一些单引号,可以通过转义符号(反斜杠符号)或者双引号来定义单引号的值;还有就是如果要处理空格问题,可以通过双引号括起来,实现最终效果,如下例:
[root@wzp
~]# cat test3
#!/bin/bash
for cities in guang zhou shang hai bei jing
do
done
[root@wzp ~]# ./test3
my favorite city is guang
my favorite city is zhou
my favorite city is shang
my favorite city is hai
my favorite city is bei
my favorite city is jing
所以可以通过灵活使用双引号解决,如下:
[root@wzp
~]# cat test3
#!/bin/bash
for cities in "guang zhou" "shang hai" "bei jing"
do
done
[root@wzp ~]# ./test3
my favorite city is guang zhou
my favorite city is shang hai
my favorite city is bei jing
生成in后面这个列表的值可以通过使用命令的输出,但这里需要协助`这个少见但是shell中常用的反引号!看下例子:
[root@wzp
~]# cat somefile
aa
bb
cc
dd
首先查看somefile这个文本文件内容
[root@wzp
~]# cat test3
#!/bin/bash
file=somefile
for words in `cat $file`
do
done
[root@wzp ~]# ./test3
the word is aa
the word is bb
the word is cc
the word is dd
这里我故意把somefile文件mv到别的地方去,结果执行文件是报错:
[root@wzp
~]# ./test3
cat: somefile: 没有那个文件或目录
1.4、使用通配符读取目录
文件通配是生产与指定通配符匹配的文件或者路径名的过程,如下例:
[root@wzp
test]# pwd
/root/test
[root@wzp test]# touch aa bb cc
[root@wzp test]# mkdir dd ee ff
先创建三个文件格三个目录
[root@wzp
~]# cat test3
#!/bin/bash
for file in $HOME/test/*
do
done
[root@wzp ~]# ./test3
/root/test/aa is a file
/root/test/bb is a file
/root/test/cc is a file
/root/test/dd is a directory
/root/test/ee is a directory
/root/test/ff is a directory
2、C语言式的for命令
这里顺便提及一下C语言式的for命令,在bash shell中也可执行。
不过C语言的for命令是通过指定变量为true值用于继续迭代的条件,当特定的条件为false时候就停止了循环,先看一个例子:
[root@wzp
~]# cat test3
#!/bin/bash
for (( i=1; i<=10; i++ ))
do
done
[root@wzp ~]# ./test3
the next num is 1
the next num is 2
the next num is 3
the next num is 4
the next num is 5
the next num is 6
the next num is 7
the next num is 8
the next num is 9
the next num is 10
3、while命令
while命令有点如if-then和for循环的结合,while通过定义要测试的命令,如果命令返回0则循环命令,如果返回非0则停止了命令集。其格式为:
while xxx
do
done
先来看一个例子:
#!/bin/bash
var=8
while [ $var -gt 0 ]
do
done
[root@wzp ~]# ./test3
8
7
6
5
4
3
2
1
4、until命令
until命令刚好和while相反,until命令的测试命令退出状态非0,bash
shell就执行列在循环中的命令,一旦测试条件返回0,就停止了循环,其格式:
until xxx
do
done
如上看起来跟while很相似,其实用法也很相似的!
先看下面的例子:
#!/bin/bash
var=24
until [ $var -eq 0 ]
do
done
[root@wzp ~]# ./test3
24
16
8
5、嵌套循环
一条循环命令可以在循环中使用任何类型的命令,包括其他循环,比如在for循环中嵌套另一个for循环,或者在一个for循环中嵌套一个while循环或until循环。
下面举两个例子:
5.1、for循环嵌套到for循环
[root@wzp
~]# cat test3
#!/bin/bash
for (( a=1; a<=3; a++ ))
do
done
[root@wzp ~]# ./test3
outside loop is 1:
inside loop is 1:
inside loop is 2:
inside loop is 3:
outside loop is 2:
inside loop is 1:
inside loop is 2:
inside loop is 3:
outside loop is 3:
inside loop is 1:
inside loop is 2:
inside loop is 3:
5.2、for循环嵌套到while循环
[root@wzp
~]# cat test3
#!/bin/bash
var1=5
while [ $var1 -ge 0 ]
do
done
[root@wzp ~]# ./test3
outer loop is : 5
inner loop : 1
inner loop : 2
outer loop is : 4
inner loop : 1
inner loop : 2
outer loop is : 3
inner loop : 1
inner loop : 2
outer loop is : 2
inner loop : 1
inner loop : 2
outer loop is : 1
inner loop : 1
inner loop : 2
outer loop is : 0
inner loop : 1
inner loop : 2
6、控制循环
如上定义了数据的各种循环方式,当我们需要某时刻退出循环的时候,如内部循环和外部循环,这个时候需要用到两个命令:
*break命令
*continue命令
如下先说说break命令控制的循环:
6.1、跳出单循环
通过break命令使得for循环和while循环、until循环可以中断跳出,先看个例子:
[root@wzp
~]# cat 6.1test
#!/bin/bash
for num in 1 2 3 4 5 6 7 8 9 10
do
done
echo 'the for loop is over !'
[root@wzp ~]# ./6.1test
the num is : 1;
the num is : 2;
the num is : 3;
the num is : 4;
the for loop is over !
同样的例子,对于while循环,如下:
[root@wzp
~]# cat 6.1test
#!/bin/bash
num=1
while [ $num -lt 10 ]
do
done
echo 'the while loop is over !'
[root@wzp ~]# ./6.1test
the number is 1
the number is 2
the number is 3
the number is 4
the while loop is over !
6.2、跳出内循环
有时候循环油嵌套,这个时候我们可以通过break来跳出循环中的内部循环,先来看个例子:
[root@wzp
~]# cat 6.2test
#!/bin/bash
for (( a=1; a<4; a++ ))
do
done
[root@wzp ~]# ./6.2test
the outer loop is:1
inner loop is:1
inner loop is:2
inner loop is:3
inner loop is:4
the outer loop is:2
inner loop is:1
inner loop is:2
inner loop is:3
inner loop is:4
the outer loop is:3
inner loop is:1
inner loop is:2
inner loop is:3
inner loop is:4
6.3、外部循环
既然有了上面的内部循环,势必可以想到有外部循环的存在,这里需要借助break命令的参数值,其格式很简单:
break n
其中n表示循环级别,默认情况是1
[root@wzp
~]# cat 6.3test
#!/bin/bash
for (( a=1; a<4; a++ ))
do
done
[root@wzp ~]# ./6.3test
the outer loop is:1
inner loop is:1
inner loop is:2
inner loop is:3
inner loop is:4
[root@wzp
~]# ./6.3test
the outer loop is:1
inner loop is:1
inner loop is:2
inner loop is:3
inner loop is:4
the outer loop is:2
inner loop is:1
inner loop is:2
inner loop is:3
inner loop is:4
the outer loop is:3
inner loop is:1
inner loop is:2
inner loop is:3
inner loop is:4
这样子我们就没有实现结束外循环的目的了,通过指定break为2,当内循环满足if-then条件的时候就把外循环指定的循环级别给结束了
OK,说完了break来说下continue了~~~
6.4、continue命令
该命令是一种提前停止循环内命令,但不结束循环。先来看一个for循环中使用continue的示例:
[root@wzp
~]# cat 6.4test
#!/bin/bash
for (( a=1; a<24; a++ ))
do
done
[root@wzp ~]# ./6.4test
the num is:1
the num is:2
the num is:3
the num is:4
the num is:5
the num is:6
the num is:7
the num is:8
the num is:18
the num is:19
the num is:20
the num is:21
the num is:22
the num is:23
7、处理循环的输出
在shell脚本中可以通过在done命令的末尾处添加处理命令实现,即为重定向>或者追加>>,看如下例子:
[root@wzp
~]# chmod u+x 7.1test
[root@wzp ~]# ./7.1test
[root@wzp ~]# cat 7.1test
#!/bin/bash
for (( a=1; a<10; a++ ))
do
done > num.txt
[root@wzp ~]# cat num.txt
the num is 1
the num is 2
the num is 3
the num is 4
the num is 5
the num is 6
the num is 7
the num is 8
the num is 9