key words    ifthen    if-then-else   嵌套if语句    test命令(数值、字符串、文件比较)
两个布尔操作符:&&      ||     双圆括号   双方括号    case 命令     、for 命令 while 命令    until命令    嵌套循环   控制循环:break continue
     所谓结构化命令指的是允许脚本根据变量值的条件或者其他命令的结果跳过
 一些命令或循环执行其他命令。
一、if语句
bash shell 中的if语句运行在if行定义的命令成功时(退出状态为0)就执行then后面的所有命令,否则(退出状态为其他非零值)then后面的命令都不会被执行,而是执行下一个结构命令。
 
1ifthen
命令格式:
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命令相反,只要测试命令的退出状态为非0bash 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 ~]#