shell 结构化命令之跳转

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011436666/article/details/73480207

说到shell脚本的结构化命令,我们不得不首先了解一下退出状态码的概念。shell中运行的每个命令都使用退出状态码(exit status)告诉shell它已经运行完毕。退出状态码是一个0-255的整数值,在命令结束运行时由命令传给shell。我们可以获取这个值并在脚本中使用。

Linux中专门提供了变量$?来保存上个已执行的命令的退出码,它的值是shell所执行的最后一条命令的退出状态码。我们可以尝试一下使用不同命令其退出状态码是什么。

退出状态码

命令成功结束时,其退出状态码为0;如果有错误,退出码就是一个正整数值,如126表示命令不可执行、127表示没找到命令、128表示无效的参数等等。

exit命令:
默认情况下,shell脚本会以脚本中的最后一个命令的退出状态码退出,我们可以用exit n来自定义状态码,注意n要在0-255之间。

一、if-then语句

if-then语句格式如下:

if command
then    
    commands
fi

在bash shell中if后面的是一个命令,如果该命令的退出状态码是0(说明该命令执行成功),那么位于then后面的命令才会被执行。注意,这和其他编程语言的if语句返回true或false不一样。只要关注了这个,这个语句使用起来很容易:

if-then

二、if-then-else语句

在if-then语句中不管命令是否执行成功,你都只有一种选择:成功则执行then中的命令;命令失败则继续往下执行。有的情况下,我们需要使用if-then-else语句:

if command
then 
    commands
else
    commands
fi

这个语句的使用也很直观,请看以下示例:

if-else-then

三、嵌套if

如果使用上面的语句仍然不能很多好的满足要求,那我们可以使用嵌套if来工作:

if command1
then 
    commands
elif command2
then
    commands2
fi

其实这里只是将else里面又嵌入了一个if-then语句,只是将else-if连起来写成了elif;我们可以随意组合嵌套,完成更复杂的逻辑。这里就不做示例了,很简单,并且后面经常会用到。

四、test命令

到目前为止,在if中用到的命令都是普通的shell命令,那么if后面是否可以测试出退出状态码以外的条件呢? 是不能的,但是我们可以用test命令来测试其他条件,只要test命令中列出的条件成立,test命令就会退出并返回退出状态码0,这样就可以完成类似于其他语言中那样的if-then语句了。
test命令的格式非常简单:test condition,condition是命令要测试的一系列参数和值相当于我们用test命令代替了之前的command命令。

test condition

如上图所示,我们在test命令里面测试一个存在的变量,会返回0,使得then中的语句会执行;相反则返回的退出状态码不为0。

test命令还有另一种常用的简便写法:单方括号 [ condition ],注意方括号距字符串必须加上一个空格。test命令可以用来判断三类条件:

  1. 数值比较
  2. 字符串比较
  3. 文件比较

下面我们来学习这几种条件测试的使用方法,后面也会经常用到这些。

1、数值比较:
数值比较功能如下表,可以用在数字和变量上。

比较 描述
n1 -eq n2 检查n1与n2是否相等(equal)
n1 -ge n2 检查n1是否大于或等于n2(greater、equal)
n1 -gt n2 检查n1是否大于n2(greater than)
n1 -le n2 检查n1是否小于或等于n2(less、equal)
n1 -lt n2 检查n1小于n2(less than)
n1 -ne n2 检查n1与n2是否不相等(not equal)

~
需要记住,bash shell只能处理整数

2、字符串比较:

比较 描述
str1 = str2 检查str1和str2是否相同
str1 != str2 检查str1和str2是不同
str1 < str2 检查str1是否小于str2
str1 > str2 检查str1是否大于str2
-n str 检查str的长度是否非0
-z str 检查str长度是否为0

~
这里需要注意两个问题:

  1. 大于号和小于号必须转移,否则shell会把它们当做重定向符号,把字符串当做文件名
  2. 大于小于的排序是按照ASCII码的顺序(即由小到大为0~9,A~Z,a~z)

我们编辑如下的脚本,用来检测变量是否长度为0。

#!/bin/bash

value1=testing
value2=""

if  [ -n $value1 ]
then
    echo "Then string $value1 not empty"
else
   echo "The string $value1 is empty"
fi

if [ -z $value2 ]
then 
    echo "The string $value2 is empty"
else
   echo "The string $value2 is not empty"
fi

if [ -z $value3 ] 
then 
    echo "The string $value3 is empty"
else
   echo "The string $value3 is not empty"
fi

执行输出后,我们发现:定义了数值的变量长度不为0;而定义为空和未定义的变量其长度均为0。

Then string testing not empty
The string  is empty
The string  is empty

空的和为初始化的变量会对我们的脚本造成很大的影响。如果不确定其值的内容,在使用之前,最好可以用-n或-z测试一下是否含有值。

3、文件比较:
文件比较是shell编程中很强大也最常用的比较形式,它允许你测试Linux文件系统上的文件和目录的状态。比较形式如下表:

比较 描述
-d file file是否存在并是一个目录
-f file file是否存在并是一个文件
-e file file是否存在
-r file file是否存在并且可读
-w file file是否存在并且可写
-s file file是否存在并且非空
-x file file是否存在并且可执行
-O file file是否存在并且属当前用户所有
-G file file是否存在并且默认组和当前用户相同
file1 -nt file2 file1是否比file2新(new than)
file1 -ot file2 file1是否比file2旧(old than)

~
这些条件使用起来也是比较简单的,我们应当先搞清楚逻辑再去做一系列的测试。

test file

如上所示,这里我们直接比较了两个文件的新旧,然而我们并没有确认这连个文件是否存在,如果没有存在的话,就可能得到一个错误的结果。我们可以使用布尔运算符来组合测试:

#复合条件测试
[ condition1 ] && [ condition2 ] 
[ condition1 ] || [ condition2 ]

test -nt

五、使用双小括号和双方括号

双小括号:
使用双小括号来使用高级数学表达式,提供了很多其他编程语言类似的运算符。格式如下:

(( expression ))

能够用在这里的表达式很多,比如:i++、i–、++i、–i之类的;逻辑求反!;一些布尔运算和位运算等等。在其他编程语言中可以用于的数学赋值或比较表达式等都可以用。

双方括号:
双方括号命令提供了针对字符串比较的高级特性。双方括号里面的表达式使用了test命令中采用的标准字符串比较。并且提供了模式匹配这个强大的特性。格式如下:

[[ expression ]]

双方括号

我们再来总结一下几种括号的使用:

方括号[ ]:类似于test命令,用判断三类条件:数值、字符串、文件
双小括号(( )):在比较中使用高级数学表达式
双方括号[[ ]]:字符串比较的升级-模式匹配(并不是所有shell都支持?)

六、case命令-简化if-then-else

当我们尝试在一组可能的值中寻找特定值,再来进行其他操作时。可能需要写下很长的if-then-else语句,这时可以使用case语句来简化脚本,case命令的格式如下:

#可以通过或操作符|在一行中使用多个pattern
case variable in
pattern1) command1;;
pattern2) command2;;
*) default commands;;
esac

case

上面这个简单的示例演示了获取当前目录并使用case来判断在哪个目录里面。不难发现使用case的场景还是比较多的。

通过这一篇大致的熟悉了结构化命令中的跳转语句,还有循环语句等者我们去学习呢。下篇预告:for/while/until等循环语句的使用。 :)

猜你喜欢

转载自blog.csdn.net/u011436666/article/details/73480207
今日推荐