第二章:shell结构化语句 if else & case


if then 语句


if语句会先执行if行定义的命令,如果返回成功的状态码0,也就是运行成功。then部分的命令才执行。如果状态是其他值,那么then部分不被执行。

例子:

[root@zw-test-db ~]# vim if.s
#!/bin/bash
# test if then
if date
then
echo "i will work"
fi
[root@zw-test-db ~]# sh if.s
Fri Jul  1 11:28:58 CST 2016
i will work

这个脚本先执行date命令,名称成功后返回状态是0,再echo文本


[root@zw-test-db ~]# vim test2

#!/bin/bash
# test if then bad
if abcde  
then 
 echo "go to bed"
fi

[root@zw-test-db ~]# sh test2
test2: line 3: abcde: command not found

报错了,echo没执行

then 可以使用多个命令,shell会将这些命令当成一个块,if语句行的那个命令返回退出状态码是0时执行这块命令,非零,则跳过这些命令


[root@zw-test-db ~]# vim test3

#!/bin/bash
testuser=oracle
if grep $testuser /etc/passwd
then 
echo "this user is $testuser "
  ls -a /home/$testuser/*.txt
fi


[root@zw-test-db ~]# sh test3
oracle:x:500:501::/home/oracle:/bin/bash
this user is oracle
/home/oracle/a.txt  /home/oracle/b.txt    /home/oracle/c.txt


如果testuser用户不存在的话,什么都不会输出

[root@zw-test-db ~]# sh test3
[root@zw-test-db ~]#


if then的另外一种写法

#!/bin/bash
testuser=oracle
if grep $testuser /etc/passwd;then 
echo "this user is $testuser "
  ls -a /home/$testuser/*.txt
fi


在执行命令的结尾加一个分号,你就能在同一行使用then语句

if - then -else

不管if是否执行成功,都有另外一种选择。如果if返回一个非0的状态,shell会继续执行下一个命令。


if   command
then command
else  
    command
fi
当if 返回的状态码是0时,then部分命令会执行,当if返回状态码非0时,shell会执行else部分的命令

[root@zw-test-db ~]# vim test4

#!/bin/bash
# test if - then -else 

testuser=badoracle
if grep $testuser /etc/passwd 
then 
 echo "you are $testuser!!"
else
 echo "you are $testuser,but you not exists this system!!"
fi


 当 testuser=badoracle时,执行了else

[root@zw-test-db ~]# sh test4
you are badoracle,but you not exists this system!!  
[root@zw-test-db ~]# vim test4


当testuser=oralce时,执行了then

[root@zw-test-db ~]# sh test4
oracle:x:500:501::/home/oracle:/bin/bash
you are oracle!!
[root@zw-test-db ~]#



嵌套if

当脚本中需要多种条件,不用分立的if-then,可以使用elif

if  command
then
     command
elif command
then 
     command
elif command
then
     command
elif command
then 
     command
......
fi



每个块都会根据哪个命令返回的状态码0来执行。shell会依次执行if语句,只有第一个返回退出状态码0的语句then部分会被执行。


test命令
注意:只能对整数比较

test命令提供了if-then语句中测试不同条件的途径。如果test列出的命令成立
test命令就会退出并返回状态码0,如果不成立则返回状态码1,这样if-then语句就失效

格式: test condition 
condition是test命令要测试的一系列参数和值。当用if-then语句中时,test命令看起来是这样的


if test condition 
then
  commands
fi

shell提供了另一种在if-then语句中声明test命令的方法

if [ condition ]
then
  commands
fi


[]方括号定义了test命令中用到的条件。注意:必须在左括号和右括号各加一个空格,否则报错

test有3类判断条件
  • 数值比较
  • 字符串比较
  • 文件比较

数值比较

n1 -eq n2  : 检查n1是否等于n2
n1 -ge n2  : 检查n1是否大于或等于n2
n1 -gt n2  : 检查 n1是否大于n2
n1 -le n2  : 检查 n1是否小于或等于n2
n1 -lt n2  : 检查 n1是否小于n2
n1 -ne n2  : 检查 n1是否不等于n2

[root@zw-test-db ~]# vim test6

#!/bin/bash
var1=10
var2=11
if[ $var1 -gt 5 ]
then 
  echo "the test value $val1 is greather than 5"
fi

if [ $var1 -eq $var2 ]
then
   echo "the values equal"
else
   echo "the value are different"
fi

[root@zw-test-db ~]# sh test6
the test value  is greather than 5
the value are different

[root@zw-test-db ~]# vim test7

#!/bin/bash
# test float
val1= `echo "scale=4; 10 / 3"|bc`
   echo "the test vale val1"
if [ val1 -gt 3 ]
then 
   echo "the result is larger than 3 "
fi

[root@zw-test-db ~]# sh test7
test7: line 3: 3.3333: command not found
the test vale val1
test7: line 5: [: val1: integer expression expected


这里使用浮点值并存储在val1中,它使用test判断这个值出错了。


字符串比较

str1  = str2    检查 str1是否等于str2
str1 != str2    检查 str1是否不等于str2
str1  < str2    检查 str1是否比str2小
str1  > str2    检查 str1是否比str2大 
-n  str1        检查str1长度是否非0
-z  str1        检查str1长度是否为0

[root@zw-test-db ~]# vim test8

#!/bin/bash
#test string euality
testuser=root

if [ $USER = $testuser ]
then
  echo "welome $testuser"
fi

[root@zw-test-db ~]# sh test8
welome root


比较字符串时,test会将所有的标点和大写也考虑在内


字符串顺序

注意: 大于小于符号必须转义,否则shell会把他们当成重定向符号,把字符串当文件名
          大于小于顺序和sort命令所采用的不同

[root@zw-test-db ~]# vim badtest

#!/bin/bash
# mis-using string compartions

val1=baseball
val2=hockey

if [ val1 > val2 ]
then
  echo "$val1 is gather than $val2"
else
 echo "$val1 is less than $val2"
fi

[root@zw-test-db ~]# sh badtest
baseball is gather than hockey

[root@zw-test-db ~]# ll -l val2
-rw-r--r-- 1 root root 0 Jul  1 15:25 val2
这个脚本是错误的,shell把>解析成了输出重定向,创建了一个val2的文件,由于重定向完成,返回状态0

#!/bin/bash
# mis-using string compartions

val1=baseball
val2=hockey

if [ val1 \> val2 ]
then
  echo "$val1 is gather than $val2"
else
 echo "$val1 is less than $val2"
fi


[root@zw-test-db ~]# sh badtest
baseball is gather than hockey



这次成功了


sort处理大小写字母的方法刚好跟test相反。


[root@zw-test-db ~]# vim test9
#!/bin/bash
# test string sort order 
val1=Testing
val2=testing

if [ $val1 \> $val2 ]
then
 echo "$val1 is gather than $val2"
else
 echo "$val1 is less than $val2" 
fi

[root@zw-test-db ~]# sh test9
Testing is less than testing

[root@zw-test-db ~]# sort sort
testing
Testing



test命令中大写会被当成小写,如果将通样的字符放进一个文件并用sort排序时,小写字母会先出现


3.字符串大写

-n -z 参数用来检查一个变量是否含有数据

vim test10


#!/bin/bash
# test string length
val1=testing
val2=''

if [ -n "$val1" ]
 then 
   echo "the string $val1 is not empty!!"
 else
   echo "the string $val1 is empty!! "
fi

if [ -z "val2" ]
then 
 echo "the string $val2 is empty!! "
else 
 echo "the string $val2 is not empty!!"
fi

[root@zw-test-db ~]# sh test10
the string testing is not empty!!
the string  is not empty!!


警告: 空的和未初始化的变量对shell脚本测试来说有可能是灾难性的影响。


文件比较


-d  file  检查file是否存在并是一个目录
-e  file  检查file是否存在
-f  file  检查file是否存在并是一个文件
-r  file  检查file是否存在并可读
-s  file  检查file是否 存在并非空 
-w  file  检查file是否 存在并可写
-x  file  检查file是否 存在并可执行
-O  file  检查file是否存在并属于当前用户所有
-G  file  检查file是否存在并且默认组与当前相同
file1 -nt file 2 检查file1是否比file2新
file1 -ot file 2 检查file1是否比file2旧

1.检查目录

[root@zw-test-db ~]# vim test11

#!/bin/bash
# test directory
 if [-d $HOME]
 then 
  echo "you home directory exists"
  cd $HOME
  ls -a
else 
 echo "There is a problem with your HOME direcotry"
fi

[root@zw-test-db ~]# sh test11
you home directory exists
?      anaconda-ks.cfg    .bash_profile  .cshrc      Downloads  .gconfd


上述代码中使用了-d,测试条件来检查用户的$HOME是否存在,如果存在,继续使用cd进入到home,并查看所有文件

2.检查对象是否存在
-e 检查文件或目录是否存在

[root@zw-test-db ~]# vim test12

#!/bin/bash
# check direcotry exists
if [ -e $HOME ]
then 
  echo "you home is exists,now check file"
  #check file exists
 if [ -e $HOME/testing ]
 then
   #file exists,apped file it
  echo "appending date to existis file " 
   date >> $HOME/testing
 else
   # the file not exists ,create new file 
   echo "createing new file"
   date > $HOME/testing
 fi
else
 echo "sorry . you not have HOME directory"
fib

[root@zw-test-db ~]# sh test12
you home is exists,now check file
createing new file
[root@zw-test-db ~]#


第一个-e判断用户是否有HOME目录,如果有,下一个-e会判断testing文件是否存在home目录中。
如果不存在,则创建一个。

3.检查文件

-e比较时候文件和目录。要确定制定的对象是个文件,必须使用-f比较

vim test13
#!/bin/bash
#check is a file
if [ -e $HOME ]
then
  echo "the home is exists,is it a file ?"
  if [ -f $HOME ]
   then
     echo "yes ,is a file!"
   else
     echo "no ,is not a file!"
     if [ -f $HOME/.bash_profile ]
     then 
      echo "but is a file "
     fi
  fi
else
 echo "sorry .the object does not exists "
fi

[root@zw-test-db ~]# sh test13
the home is exists,is it a file ?
no ,is not a file!
but is a file
[root@zw-test-db ~]#


首先-e判断home是否存在,如果存在,用-f测试它是否是一个文件,如果它不是文件,用-f测试$HOME/.bash_profile是不是一个文件
 

4.检查是否可读

[root@zw-test-db ~]# vim test14

#!/bin/bash
# test you can read file
pwdfile=/etc/shadow

# first test file exists,and is a file
 if [ -f $pwdfile ]
    then
     #now test you can read it
     if [ -r $pwdfile ]
        then
         tail $pwdfile
        else
        echo "sorry,you can not read $pwdfile "
     fi
 else
  echo "sorry,the file $pwdfile  does not exists"
fi

[oracle@zw-test-db /]$ sh test14
sorry,you can not read /etc/shadow


由于我是oracle用户执行的,所以不能查看密码文件


5.检查空文件
-s 检查文件是否为空,尤其删除时

[root@zw-test-db ~]# vim test15

#!/bin/bash
#test file is empty
file=t15test
touch $file

if [ -s $file ]
  then 
        echo "the $file is exists and had data in it "
  else
       echo "the $file is exists and empty"
fi
 date > $file
if [ -s $file ]
   then 
     echo "the $file is exists and had data in it"
   else
     echo "the $file is exists and empty"
fi

[root@zw-test-db ~]# sh test15
the t15test is exists and empty
the t15test is exists and had data in it


6.检查文件是否可写
-w 判断是否对文件有可写权限

[root@zw-test-db ~]#vim  test16

#!/bin/bash
# checking if a file is writeable

logfile=$HOME/t16
touch $logfile
chmod u-w $logfile
now=`date +%y%m%d-%H%M`

if [ -w $logfile ]
   then
     echo "the program can write $logfile" >logfile
     echo "the first attempt succeeded" 
   else
     echo "the first attempt  filed"
fi
chmod u+w $logfile
if [ -w $logfile ]
     then 
     echo "the program can write $logfile" >logfile
     echo "the first attempt succeeded" 
  else
      echo "the first attempt  filed"
fi

[root@zw-test-db ~]# sh test16
the first attempt  filed
the first attempt succeeded


7.检查文件是否可执行
-x 是判断文件是否可执行的一个方法

[root@zw-test-db ~]# vim test17

#!/bin/bash
# test file execution 
if  [ -x test16 ]
   then 
      echo "you can run the script"
     sh test16
else
   echo "sorry, you can't execute the script "
fi

csh test17
sorry, you can't execute the script


8.检查所属关系
-0 可以轻松测试你是否是文件的属主

[root@zw-test-db ~]#  vim test18
#!/bin/bash
# test file ownership
if [ -O /etc/passwd ]
   then 
      echo "you are the owner of the /etc/passwd file"
  else 
     echo "sorry. you are not the owner of the /etc/passwd file"
fi

[root@zw-test-db ~]# sh test18
you are the owner of the /etc/passwd file


9.检查默认属组关系
-G检查文件默认属组,只会检查默认组而非用户所属的所有组。

[root@zw-test-db ~]# vim test19

#!/bin/bash
# check file group test

if [ -G $HOME/testing ]
   then 
     echo "you are in the same group as the file"
  else 
    echo "the file not owned by your group "
fi

[root@zw-test-db ~]# sh test19
you are in the same group as the file

[root@zw-test-db ~]# chgrp dba /root/testing
[root@zw-test-db ~]# sh test19
the file not owned by your group
[root@zw-test-db ~]#


第一次用root成功了,第二次改成dba组了,所以失败了


10.检查文件日期
-nt  比较会判定某个文件是否比另一个文件更新。如果文件更新,那它会有一个比较近的文件创建日期。
-ot  比较某个文件是否比另一个文件更老。如果文件更老,它会有一个更早的创建日期

[root@zw-test-db ~]# vim  test20

#!bin/bash
# test file dates

if [ $HOME/test19 -nt $HOME/test18 ]
  then 
     echo "test19 file is newer than test18"
  else
     echo "test18 file is newer than test19 "
fi

if [ $HOME/test17  -ot $HOME/test19 ]
   then 
    echo "test17 file is older than test19 file"
fi


[root@zw-test-db ~]# sh test20
test19 file is newer than test18
test17 file is older than test19 file


if - then 语句允许使用布尔逻辑来组合测试。
[condition] && [condition]  and 两边条件都必须满足
[condition] || [condition]  or  任何一边满足,then部分就会执行

[root@zw-test-db ~]# vim  test22
#!/bin/bash
# testing compound comparisons

if [ -d $HOME ] && [ -w $HOME/testing ]
then
     echo "the file exists and you can write to it"
else 
     echo "i cannot write to the file"
fi

[root@zw-test-db ~]# sh test22
the file exists and you can write to it


[root@zw-test-db ~]# rm -f testing
[root@zw-test-db ~]# sh test22
i cannot write to the file


使用 and布尔运算符时,两个比较必须满足。第一个检查home目录是否存在,第二个会检查home目录是否有testing文件,以及是否有写的权限。
如果任意一个失败,if语句就会失败,shell就会进入到else部分。如果两个都通过,if语句就通过,就会执行then的部分。



if-then的高级特性

 shell提供了可以在if-then语句中使用的高级特性:
  •  用于数学表达式的双尖括号
  • 用于高级字符串处理功能的双括号

1.使用双尖括号

  双尖括号命令允许你将高级数学表达式放入比较中。test命令只允许比较中进行简单的运算操作。
  双尖括号命令格式如下:
  ((expression))
  术语expression可以是任意的数学赋值或比较表达式。

val++          后增
val--          后减
++val          先增
--val          先减
!             逻辑求反
~              位求反
**             幂运算
<<             左位移
>>             右位移
&              位布尔和
|              位布尔或
&&             逻辑和
||             逻辑或


你可以在if语句中用双尖括号命令,也可以在脚本中的普通命令使用来赋值

vim test23
#!/bin/bash
# using double parenthesis
     
val1=10
if (( $val1 ** 2 > 90 ))
then 
   (( val2 = val1 ** 2  ))
echo "the square of $val1 is $val2"
fi


1.使用双括号

 双括号提供了针对字符串比较的高级特性。

[root@zw-test-db ~]# vim test24

#!/bin/bash
# test pattern 

if [[ $USER == r* ]]
  then 
    echo "hello $USER"
else
  echo "sorry. i do not know you "
fi

[root@zw-test-db ~]# sh test24
hello root

双括号命令匹配了$USER环境变量,看它是否以r开头,如果是执行then命令


case  命令


你会经常发现自己尝试计算一个变量的值或者在一组可能的值中寻找特定的值,在这种情形下,必须写出 if-then-else语句,像这样

[root@zw-test-db ~]#

#!/bin/bash
# looking for a possible value

if [ $USER = root ]
  then 
    echo " welcome $USER"
    echo "please enjoy visit"
elif [ $USER = oracle ]
  then  
    echo " welcome $USER"
    echo "please enjoy visit"
elif [ $USER = mysql ]
  then 
    echo "this mysql account"
elif [ $USER = zw ]
   then 
    echo "do not forget to logout when you are done "
else
   echo "sorry,you are not allowed here "
fi

[root@zw-test-db ~]# sh test25
sorry,you are not allowed here


你可以使用case 命令,而不用写出那么多elif语句来不断地检查相同的变量值。
case命令会检查单个变量列表格式的多个值:

case variable in
pattern1 | pattern2) commands1;;
pattern3) command2;;
*) default commands;;
esac


case 命令会将指定的变量同不同模式进行比较。如果变量和模式匹配,那么shell会执行为该模式指定的命令。
你可以通过竖线操作符号来分割模式,在一行列出多个模式。星号会捕获所有跟所有列出的模式都不匹配的值。
这里有个将if-then-else程序转换成用case命令的例子:

vim test26
#!/bin/bash
# using the case command

case $USER in
root | mysql )
echo "welcome $USER"
echo "please enjoy the visit";;
zw)
 echo "this is zw account";;
oracle)
 echo "this is oracle account";;
* )
 echo "sorry , you are not allowed here" ;;
esac

[root@zw-test-db ~]# sh test26
welcome root
please enjoy the visit









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值