)
上一篇文章把构建基本shell脚本从创建到执行、从变量到数学运算、从bc浮点计算到退出状态码整个过了一遍总算是能写一些简单的脚本了。但有一个问题始终绕不过去之前写的脚本都是从头到尾顺序执行每一条命令都会跑一遍没有任何选择和判断的能力。比如脚本里想根据不同的情况做不同的事情或者想检查某个文件存不存在再决定要不要继续执行这些需求之前的写法完全满足不了。课程推进到了结构化命令这一章主要内容就是if-then语句、test命令和各种条件测试学完之后脚本终于有了长脑子的感觉。先说一下if-then语句的基本结构。在其他编程语言中if语句后面跟的是一个等式该对象的值若为TRUE则执行接下来的命令若为FALSE则不执行。但bash shell的if语句有点不一样它会运行if后面的那个命令如果该命令的退出状态码是0即命令成功运行则位于then后面的命令才会被执行。如果该命令的退出状态码是其他值then后面的命令就不会被执行bash shell会跳过这个if-then语句去执行脚本中后面的命令。这个设计刚开始让我有点不习惯因为直觉上以为if后面应该是条件表达式而不是命令但理解了退出状态码的概念之后就明白了bash就是在检查命令是否执行成功。if-then语句的结束标记是fi表示这个语句块到此结束。语法格式上可以把then和if放在同一行中间用分号隔开这样写起来更紧凑比如if command; then。当需要两种选择时if-then-else语句就派上用场了。当命令返回一个非零退出状态码时if-then-else语句能够执行else部分的命令。这个很好理解条件成立走then条件不成立走else。如果分支更多可以用elif继续扩展这样就可以避免书写多个独立的if-then语句结构更清晰。if-then语句只能测试命令的退出状态码但很多时候我们想测试的是其他条件比如两个数的大小关系、字符串是否相等、文件是否存在。这时候test命令就出场了。test命令提供了在if-then语句中测试不同条件的途径如果test命令中列出的条件成立test命令就会退出并返回退出状态码0这样if-then语句就与其他编程语言中的if-then语句以类似的方式工作了。如果条件不成立test命令就会返回非零的退出状态码。test命令有两种语法格式一种是if test condition另一种是用方括号代替test命令写作if [ condition ]。注意方括号前后必须用空格和里面的条件隔开否则无法正常运行。test命令可以判断三类条件数值比较、字符串比较和文件比较。数值比较包括-eq等于、-ne不等于、-gt大于、-ge大于等于、-lt小于、-le小于等于只能进行整数运算比较不能处理浮点数值。字符串比较包括相等性比较、顺序比较和大小比较字符串相等性比较时标点和大小写都会考虑在内字符串顺序比较时大于号和小于号必须用反斜杠转义。需要注意大小写字母排序与sort命令恰好相反因为test使用的是ASCII顺序而sort使用的是系统本地化设置。-n和-z可以检查一个变量是否含有数据-n检查字符串长度是否非零-z检查字符串长度是否为零。文件比较测试的是Linux文件系统上文件和目录的状态常用的有-d检查文件是否存在且为目录、-e检查文件是否存在、-f检查文件是否存在且为文件、-r检查文件是否存在且可读、-w检查是否存在且可写、-x检查是否存在且可执行、-s检查文件是否存在且非空。当需要同时检查多个条件时复合条件测试就很有用了。可以使用布尔逻辑来组合测试表示与即两个条件都要满足才返回TRUE||表示或只要满足其中一个就返回TRUE。比如[ condition1 ] [ condition2 ]表示condition1和condition2同时成立[ condition1 ] || [ condition2 ]表示至少有一个成立。双括号和双方括号是bash提供的更高级的测试方式。双括号命令(( expression ))允许在比较过程中使用高级数学表达式而test命令只能在比较中使用简单的算术操作。双括号提供了更多的数学符号比如、--、**等而且不需要将大于号或小于号转义。双方括号命令[[ expression ]]提供了模式匹配功能可以对标准字符串进行比较支持正则表达式匹配。把今天的内容和之前学的串在一起看之前写的脚本都是一条道走到黑现在有了if-then、test、复合条件这些工具脚本终于能根据不同情况做出不同的反应了。比如可以写一个脚本先检查某个文件是否存在存在就备份不存在就报错退出。可以检查用户输入的数字是否在合理范围内不在就提示重新输入。可以检查当前运行的用户是不是root不是就拒绝执行。这些能力让脚本从顺序执行的命令列表真正变成了具备判断逻辑的程序。后续再写脚本的时候遇到需要判断的场景就有办法了。希望这篇文章能给正在学习结构化命令的同学一些参考有问题欢迎来交流。