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