key words : if — then if-then-else 嵌套 if 语句 test 命令(数值、字符串、文件比较)
两个布尔操作符:&& || 双圆括号 双方括号 case 命令 、for 命令 while 命令 until命令 嵌套循环 控制循环:break continue
所谓结构化命令指的是允许脚本根据变量值的条件或者其他命令的结果跳过
一些命令或循环执行其他命令。
一、if语句
bash shell 中的if语句运行在if行定义的命令成功时(退出状态为0)就执行then后面的所有命令,否则(退出状态为其他非零值)then后面的命令都不会被执行,而是执行下一个结构命令。
1 、 if — then
命令格式:
if command
then commands
fi
例:
[root@localhost ~]# cat testif1
#!/bin/bash
if date; then
echo it work
fi
[root@localhost ~]# ./testif1
2011年 07月 20日 星期三 21:41:03 EDT
it work
[root@localhost ~]#
如果用户wlt存在,则列出某些目录:
[root@localhost ~]# cat testif2
#!/bin/bash
testuser=wlt
if grep $testuser /etc/passwd
then
ls -a /home/$testuser/.b*
fi
[root@localhost ~]# ./testif2
wlt:x:501:501::/home/wlt:/bin/bash
/home/wlt/.bash_history /home/wlt/.bash_profile
/home/wlt/.bash_logout /home/wlt/.bashrc
2、if-then-else语句,比if -then 语句多一个判断语句
格式:
if command
then
commands
else
commands
fi
例:测试用户是否存在
[root@localhost ~]# cat testif3
#!/bin/bash
testuser=Baduser
if grep $testuser /etc/passwd
then
ls -a /home/$testuser/
else
echo "the user $testuser does not exit on this system"
fi
[root@localhost ~]# ./testif3
the user Baduser does not exit on this system
[root@localhost ~]#
3、嵌套if语句,可进行多重判断
格式:
if command1
then
commands
elif command2
then
more commands
fi
或者可以把多个elif语句串在一起,创建一个强大的 if —then—elif组
if command1
then
command set1
elif command2
then
command set2
elif command3
then
command set3
……
bash shell按顺序执行if语句,只有第一个返回0退出状态的命令后面的then语句会被执行。
这种为单个比较变量查找特定值的需求用case更简洁,可以避免嵌套很多if—then语句。
二、test命令
test是个比较灵巧的工具,结合if-then等结构化语句使用,能够进行数值比较、字符串比较和文件比较
1、数值比较
数值比较所需比较符号:
-eq :等于 -ge: 大于等于
-lt:小于 -le:小于等于
-gt: 大于 -ne:不等于
例:
[root@localhost ~]# cat test
#!/bin/bash
val1=10
val2=11
if [ $val1 -gt 5 ] 注意:中括号前后要有空格
then
echo "the test value $val1 is greater than 5"
fi
if [ $val2 -eq 12 ]
then
echo "the values are equal"
else
echo "the values are diffrent"
fi
[root@localhost ~]# ./test
the test value 10 is greater than 5
the values are diffrent
2、字符串比较
= 相同 > 大于
! = 不同 -n 长度大于 0
< 小于 -z 长度等于 0
注意事项: 1 、大于小于号一定要转义,否则 bash shell 会当重定向符号使用
2 、 test 中大写字母小于小写字母,与 sort 的排序方法相反
[root@localhost ~]# cat test
#!/bin/bash
val1=wenliting
val2=liting
if [ $val1 > $val2 ]
then
echo "$val1 is greater than $val2"
fi
[root@localhost ~]# ./test 因为退出状态码为 0 ,所以 if 语句可以顺利执行
wenliting is greater than liting
[root@localhost ~]# ls 但会发现当前目录下生成了 liting 这个文件
\ install.log messages.110720 testcase testif1
anaconda-ks.cfg install.log.syslog test testfor1 testif2
Desktop liting test1 testfor2 testif3
free.rd log
下面是正确的例子:
[root@localhost ~]# cat test
#!/bin/bash
val1=wenliting
val2=liting
if [ $val1 \> $val2 ]
then
echo "$val1 is greater than $val2"
fi
if [ -z $val1 ];then
echo "the string '$val1' is empty"
else
echo "the string '$val1' has sth"
fi
[root@localhost ~]# ./test
wenliting is greater than liting
the string 'wenliting' has sth
[root@localhost ~]#
3、文件比较
shell脚本中最最强大和最常用的一类测试比较
-d 检查文件是否存在并且是目录 -O 是否存在并且为当前用户所有
-f 是否存在并且是文件 -G 是否存在并且默认组是当前用户组
-e 是否存在 a -nt b :a是否比b新
-r/w/x 是否存在并且可读/写/执行 a -ot b : a是否比b旧
-s 是否存在并且不为空
例:
[root@localhost ~]# cat test
#!/bin/bash
if [ -e $HOME ]
then
echo "object exists,is it a file?"
if [ -f $HOME ];then
echo "yes,it's a file"
else
echo "no,it's not a file"
if [ -f $HOME/.bash_history ];then
echo "but,$HOME/.bash_history is a file"
fi
fi
else
echo "sorry,object doesn't exist"
fi
[root@localhost ~]# ./test
object exists,is it a file?
no,it's not a file
but,/root/.bash_history is a file
三、复合检查条件与if-then 高级特征:
1、两个布尔操作符:&& ||
1)用在if-then 语句中判断时:
condition1 && condition2 表示必须同时满足两个条件才执行 then 后面的命令
condition || conditon2 满足两个条件之一即可执行 then 后面的命令
例:
[root@localhost ~]# cat test
#!/bin/bash
if [ -d $HOME ] && [ -w $HOME/testing ]
then
echo "object exists,and you can write to it"
else
echo "can't write to the file"
fi
[root@localhost ~]# ./test
can't write to the file
2)用在执行两条命令时:
command1 && command2 command1 执行成功才会执行 command2
command1 || command2 command1执行成功了就不再往后执行,否则执行command2
2、if-then 高级特征
1 )双圆括号 ——表示数学表达式,提供更多高级数学符号
格式:(( expression ))
val++ 后增量 << 逐位左移
val-- 后减量 >> 逐位右移
++val 前增量 & 逐位布尔逻辑与
--val 前减量 | 逐位布尔逻辑或
** 取幂 && 布尔逻辑与
! 逻辑否定 || 布尔逻辑或
~ 逐位取反
例:
[root@localhost ~]# cat test
#!/bin/bash
val1=10
if (($val1**2>90));then
((val2=$val1**2))
echo "the square of $val1 is $val2"
fi
[root@localhost ~]# ./test
the square of 10 is 100
[root@localhost ~]#
2 )双方括号——提供高级字符串处理功能
格式: `expression`
双方括号中的expression使用在test命令中的标准字符串比较。但是它提供了test命令没有的另一个功能: 模式匹配,在模式匹配中,可以定义与字符串相符合的正则表达式
[root@localhost ~]# cat test
#!/bin/bash
if [[ $USER==r* ]];then 用方括号的时候别忘了留空格
echo "hello,$USER"
else
echo "sorry,i don't know you"
fi
[root@localhost ~]# ./test
hello,root
[root@localhost ~]#
四、case命令
case命令将指定的变量与不同的模式进行比较,如果变量与模式匹配,shell执行该模式指定的命令,可以在一行中列出多个模式,用竖条操作符分开每个模式,星号是与任何列出的模式都不匹配的所有值。
格式:
case variable in
pattern1 | pattern2) commands1;;
pattern3) commands2;;
*) default commands;;
esac
例 :
[root@localhost ~]# cat testcase
#!/bin/bash
shopt -s -o nounset
case @USER in
Lily | Sary)
echo "welcome,@USER"
echo "please enjoy your visit";;
wlt)
echo "hi,one,how have you been";;
ivy)
echo "hei,long time no see!";;
*)
echo "sorry,you are not allowed here"
esac
[root@localhost ~]# ./testcase
sorry,you are not allowed here
五、for 命令
bash shell 提供 for 命令来创建通过一系列重复的循环。每次重复使用系列中的一个值执行一个定义命令集。
基本格式:
for var in list
do
commands
done
for ((i=1;i<=100;i++))
do
commands
done
1 、读取列表中的值 : ( 批量创建用户 )
[root@localhost ~]# chmod u+x testfor1
[root@localhost ~]# cat testfor1
#!/bin/bash
for i in 1 2 3 4 5 6 7
do
echo the next number is $i
done
[root@localhost ~]# ./testfor1
the next number is 1
the next number is 2
the next number is 3
the next number is 4
the next number is 5
the next number is 6
the next number is 7
2、读取列表中的复杂值
for 认为每个值都用空格分离,对单引号、空格等,需要用转义字符 \ 或双引号进行处理
例:
[root@localhost ~]# cat testfor2
#!/bin/bash
for test in I don't like New York,I like Lijiang
do
echo word:$test
done
[root@localhost ~]# ./testfor2
./testfor2: line 2: unexpected EOF while looking for matching `''
./testfor2: line 6: syntax error: unexpected end of file
单引号是敏感字符,要转义,而New York是个城市名,用双引号可以当一个整体字符
[root@localhost ~]# cat testfor2
#!/bin/bash
for test in I don\'t like "New York", I like Lijiang
do
echo word:$test
done
[root@localhost ~]# ./testfor2
word:I
word:don't
word:like
word:New York,
word:I
word:like
word:Lijiang
3、从变量读取列表
用for循环可以读取存储于变量中的一个值列表
例:
[root@localhost ~]# cat testfor1
#!/bin/bash
Number="1 2 3 4 5 6 7"
for i in $Number
do
echo do you like $i ?
done
[root@localhost ~]# ./testfor1
do you like 1 ?
do you like 2 ?
do you like 3 ?
do you like 4 ?
do you like 5 ?
do you like 6 ?
do you like 7 ?
4、读取命令中的值
用反引号来执行生成输出的任何命令
[root@localhost ~]# cat testfor3
#!/bin/bash
file=/etc/resolv.conf
for word in `cat $file`
do echo $word
done
[root@localhost ~]# ./testfor3
;
generated
by
/sbin/dhclient-script
nameserver
110.65.107.2
search
localdomain
5、使用通配符读取目录
[root@localhost ~]# cat test
#!/bin/bash
for file in /home/wlt/*
do
if [ -d "$file" ];then
echo "$file is a directory"
elif [ -f "$file" ];then
echo "$file is a file"
fi
done
[root@localhost ~]# ./test
/home/wlt/vimrc is a file
求100之内的数相加的和是多少
[root@localhost ~]# cat test
#!/bin/bash
for ((i=1;i<=100;i++))
do
((sum+=$i))
done
echo "1+2+3+4...+100=$sum"
六、while 命令
while命令有点像if-then 语句和for循环的结合,它在每次迭×××始时检查测试的命令,测试命令返回非零退出状态代码时停止执行命令集,否则陷入无限循环。
命令格式:
while test command
do
other commands
done
例:
[root@localhost ~]# cat test
#!/bin/bash
var=5
while echo $var 定义了两条 test 命令,第一条简单列出 var 的值
[ $var -ge 0 ] 第二条决定循环条件
do
echo "this is inside the loop"
var=$[ $var-1 ]
done
[root@localhost ~]# ./test
5
this is inside the loop
4
this is inside the loop
3
this is inside the loop
2
this is inside the loop
1
this is inside the loop
0
this is inside the loop
-1
七、until命令
until 命令与 while 命令相反,只要测试命令的退出状态为非 0 , bash shell 就会执行列在循环中的命令,一旦测试条件返回的退出状态为 0 ,循环停止。
例:
[root@localhost ~]# cat test
#!/bin/bash
var=100
until [ $var -eq 0 ]
do
echo inside the loop: $var
var=$[ $var-25 ]
done
[root@localhost ~]# ./test
inside the loop: 100
inside the loop: 75
inside the loop: 50
inside the loop: 25
八、嵌套循环
嵌套循环也叫内循环,指在一条循环语句中使用任何类型的命令,包括其他循环命令。使用嵌套循环时要小心,因为是在一个迭代内部执行另一个迭代,增加了正在运行的命令的运行次数。
例:
在 for 循环里面嵌套 for 循环
[root@localhost ~]# cat test
#!/bin/bash
for ((a=1;a<=3;a++))
do
echo "starting loop: $a"
for ((b=1;b<=3;b++))
do
echo "inside loop: $b"
done
done
在 while 循环里面嵌套 for 循环:
[root@localhost ~]# cat test
#!/bin/bash
var1=4
while [ $var1 -ge 0 ]
do
echo "outer loop:$var1"
for ((var2=1;$var2<3;var2++))
do
var3=$[ $var1*$var2 ]
echo "inside loop:$var1*$var2=$var3"
done
var1=$[ $var1-1]
Done
until循环和while循环的结合:
[root@localhost ~]# cat test
#!/bin/bash
var1=3
until [ $var1 -eq 0 ]
do
echo "outer loop:$var1"
var2=1
while [ $var2 -lt 4 ]
do
var3=`echo "scale=4;$var1/$var2" | bc`
echo "inner loop:$var1/$var2=$var3"
var2=$[ $var2+1 ]
done
var1=$[ $var1-1 ]
done
九、利用循环处理文件数据
通过 使用嵌套循环和改变环境变量 IFS可以对文件进行单独行处理,这个应用的典型例子是对/etc/passwd文件的处理:
[root@localhost ~]# cat test
#!/bin/bash
#IFS.OLD=$IFS
IFS=$'\n'
for entry in `cat /etc/passwd`
do
echo "varlues in $entry "
IFS=:
for value in $entry
do
echo "$value"
done
done
[root@localhost ~]# ./test |more
varlues in root:x:0:0:root:/root:/bin/bash
root
x
0
0
root
/root
/bin/bash
varlues in bin:x:1:1:bin:/bin:/sbin/nologin
bin
x
1
1
bin
/bin
/sbin/nologin
十、控制循环
我们不想让循环按部就班完成它所有的迭代的时候可以用两条命令控制循环内部发生的事:
break and continue
1、break
使用break命令可以简单跳出在处理过程中的所有循环。
可以使用break的几种循环:
1 )跳出单循环
[root@localhost ~]# cat test
#!/bin/bash
for var1 in $(seq 1 10)
do
if [ $var1 -eq 5 ];then
break
fi
echo "iteration number:$var1"
done
echo "the for loop is completed"
[root@localhost ~]# ./test
iteration number:1
iteration number:2
iteration number:3
iteration number:4
the for loop is completed
2)跳出内循环
使用多循环时可以用break命令终止最里面的内循环
[root@localhost ~]# cat test
#!/bin/bash
for ((a=1;a<4;a++))
do
echo "outer loop:$a"
for ((b=1;b<100;b++))
do
if [ $b -eq 5 ]
then
break
fi
echo "inner loop:$b"
done
done
[root@localhost ~]#
3)跳出外循环
有时候处于内循环但需要终止外循环可以使用 break n 命令
[root@localhost ~]# cat test
#!/bin/bash
for ((a=1;a<4;a++))
do
echo "outer loop:$a"
for ((b=1;b<100;b++))
do
if [ $b -gt 5 ]
then
break 2
fi
echo "inner loop:$b"
done
done
2、continue 命令
continue命令可以提前停止循环内命令而不完全终止循环。和break一样,continue 命令也可以指定要继续的循环级别:continue n
[root@localhost ~]# ./test
Iteration:1
The result of 1*1 is 1
The result of 1*2 is 2
Iteration:2
The result of 2*1 is 2
The result of 2*2 is 4
Iteration:3
Iteration:4
The result of 4*1 is 4
The result of 4*2 is 8
[root@localhost ~]#