许多程序要就对shell脚本中的命令施加一些逻辑控制流程。
结构化命令允许你改变程序执行的顺序。不一定是依次进行的
12.1 使用if-then语句
如下格式:
if command
then
commands
fi
if语句会允许if后面的那个命令,如果该命令的退出码的0(代表成功了)位于then部分的命令就会被执行。否则不执行。
例子:
#!/bin/bash
# if then test
if pwd
then
echo “pwd success”
fi
# this is error cmd, no run then commands
if thisErrorCmd
then
echo “Com success”
fi
echo “this end”
then部分可以使用不止一条命令。bash shell会把这些命令当成一个块,要么不执行,要么全部执行。
例子:
#!/bin/bash
# if then test
testuser=xcy
if grep $testuser /etc/passwd
then
echo "this is first command"
echo "this is second command"
echo "i can even put in other commands besides echo:"
ls -a /home/$testuser/.b*
fi
12.2 if –then-else语句
另外一组命令:
if command
then
commands
else
commands
fi
else 后面也可以接多条命令。
例子:
#!/bin/bash
# if then test
testuser=hshsh
if grep $testuser /etc/passwd
then
echo "this is first command"
echo "i can even put in other commands besides echo:"
ls -a /home/$testuser/.b*
else
echo "error: this is first command"
echo "error: not find user $testuser"
fi
12.3嵌套if
可以这样
if command
then
if commands
then
commands
else
commands
fi
else
commands
fi
这种嵌套问题在于代码不易阅读,很难理清楚逻辑流程。下面介绍另外一种方式:
if command1
then
command1s
elif command2
then
command2s
elif command3
then
command3s
else
commands
fi
例子:
#!/bin/bash
# if-then-elif test, can changed testuser testuser1
testuser=xcy
testuser1=xcy
if grep $testuser /etc/passwd
then
echo "step0:i can even put in other commands besides echo:"
ls -a /home/$testuser/.b*
elif grep $testuser1 /etc/passwd
then
echo "step1: i can even put in other commands besides echo:"
ls -a /home/$testuser1/.b*
else
echo "not find user $testuser and $testuser1"
fi
12.4 test命令
test提供了在if-then语句中测试不同条件的的途径。
如果test命令中列出的条件成立,test命令就就会退出并返回退出状态码0。这样if then就会顺利执行了。
如果不成立,test命令就会退出并返回非0的退出状态码。if-then语句就不会再被执行了
格式如下:
if test condition
then
commands
fi
当你假如一个条件时,test会测试该条件。
(1)如果不写condition部分,会以非0的退出状态码退出。
还可以这么写:
// 注意condition两边一定要有空格。
if [ condition ]
then
commands
fi
test 可以判断三类条件:
数值比较
字符串比较
文件比较
12.4.1 数值比较
下面是数值比较命令的表:不能在test命令中使用浮点数
n1 –eq n2 相当于 ==
n1 –ge n2 相当于 >=
n1 –gt n2 相当于 >
n1 –le n2 相当于 <=
n1 –lt n2 相当于 <
n1 –ne n2 相当于 !=
12.4.2 字符串比较
str1 = str2 是否相同
str1 != str2 是否不相同
str1 < str2 str1是否小于str2
str1 > str2 str1是否大于str2
-n str1 长度是否非0
-z str1 长度是否为0
1. 字符串相等性
直接用=, != 就行了
2. 字符串顺序:有两个注意事项
(1)大于号小于号必须转义,否则会被认为是重定向
(2)大于和小于顺序 和 sort采用的不同。
比较测试中大写字母是小于小写字母的。sort命令恰好
例子:
#!/bin/bash
# test command test
if test
then
echo "step1 true"
else
echo "step1 false"
fi
num=8
if [ $num -ge 8 ] # 还可以接 –le -eq 等一大堆
then
echo "step2 num >= 8"
else
echo "step2 num not >= 8"
fi
testuser=xcddy
if [ $USER != $testuser ]
# if [ $USER = $testuser ]
then
echo "step3, user not $testuser"
else
echo "step3, user is $testuser"
fi
str1=Test1 # small
str2=test1 # big
if [ $str1 \> $str2 ] # 需要转义
then
echo "step4, $str1 > $str2"
else
echo "step4, $str1 <= $str2"
fi
str3=
if [ -z $str3 ]
#if [ -n $str3 ]
then
echo "step5, $str3 len is 0"
else
echo "step5, $str3 len is not 0"
fi
12.4.3 文件比较
最为强大,也是用的最多的比较形式。允许测试liunx文件系统上文件和目录的状态
-d file 是否存在并且是目录
-e file 是否存在
-f file 是否存在并且是文件
-r file 是否存在并可读
-s file 是否存在并非空
-w file 是否存在并可写
-x file 是否存在并可执行
-O file 是否存在并属当前用户所有 // 大写的O
-G file 是否存在并默认组与当前用户相同
file1 –nt file2 file1是否比file2新
file1 –ot file2 file1是否比file2旧
例子:
#!/bin/bash
jump_dir=testDir
if [ -d $jump_dir ]
then
echo "$jump_dir is exist, now change in this:"
cd $jump_dir
echo -n "now pwd:"
pwd
else
echo "$jump_dir is not exist, should create Dir"
mkdir $jump_dir
echo "change Dir to $jump_dir"
cd $jump_dir
echo -n "now pwd:"
pwd
fi
test_file=moduleok
if [ -e $test_file ]
then
echo "$test_file is exist"
mv moduleok running
sleep 3
mv running moduleok
else
echo "$test_file is not exist, touch this:"
touch $test_file
mv moduleok running
sleep 3
mv running moduleok
fi
echo "check up dir:"
cd ..
echo -n "now pwd:"
pwd
run_test=test2
if [ -x $run_test ]
then
echo "you can run the script: $run_test"
./$run_test
else
echo "you are unable to execute the script: $run_test"
fi
file1=test1
file2=test5
if [ $file1 -nt $file2 ]
then
echo "$file1 is new, $file2 is old"
else
echo "$file1 is old, $file2 is new"
fi
12.5 符合条件测试
if-then 允许使用布尔逻辑来组合测试:
(1)[ condition1 ] && [ condition2 ]:使用AND布尔运算符来组合两个条件
(2)[ condition1 ] || [ condition2 ]:使用OR来组合两个条件
12.6 if-then的高级特性
提供了两项可在if-then语句中使用的高级特性:
(1)用于数学表达式的双括号
(2)用于高级字符串处理功能的双方括号
12.6.1 使用双括号
test命令只能在比较中使用简单的算数操作。
允许你在比较过程中使用高级数学表达式。提供了更多的数学符号
val++, val-- 后增 后减
++val, --val 先增 先减
! 逻辑求反
~ 位求反
** 幂运算
<< 左位移 >> 右位移
& 位布尔和 | 位布尔或
&& 逻辑和 || 逻辑或
双括号里面的大于号不需要转义
12.6.2 使用双方括号
注意不是所有的shell都支持双方括号。
在模式匹配中可以定义一个正则表达式来匹配字符串
[[ expression ]]
expression使用了test命令中采用的标准字符串比较,但它提供了test命令未提供的另一个特性 – 模式匹配
例子:
#!/bin/bash
# (( )) test
val=10
#val=5
if (( val ** 2 > 90 ))
then
echo "$val ^ 2 > 90"
(( val2 = $val ** 2 ))
echo "Result: $val ^ 2 is $val2"
else
echo "$val ^ 2 < 90"
fi
str1=xcyhaha
if [[ $str1 == xcy* ]]
then
echo "str1 == xcy* , str1 is $str1"
else
echo "str1 != xcy* , str1 is $str1"
fi
12.7 case命令
有了case命令就不需要再写出所有的elif语句来不停的检查同一个变量的值了。
case命令会采用列表格式来检查单个变量的多个值。
语法:注意后面的那两个分号
case variable in
pattern1 | pattern2 ) commands1;;
pattern3) commands2;;
*) default commands;;
esac
case命令会将指定的变量与不同模式进行比较。如果变量和模式匹配,那么shell会执行为改模式指定的命令。
可以通过竖线操作符在一行中分割出多个模式模式。
*星号会捕获所有与已知模式不匹配的值。
case命令提供了一个更清晰的方法来为变量每个可能的值指定不同的选项。
例子:
#!/bin/bash
var=68
case $var in
3)
echo "var == 3";;
4)
echo "var == 4";;
5)
echo "var == 5";;
7|6)
echo "var == 6|7";;
*)
echo "var defaule";;
esac