Linux 命令行与 shell 脚本编程大全 12 使用结构化
2019-12-31 本文已影响0人
asing1elife
介绍可以对 shell 脚本中的命令进行逻辑流程控制的结构化命令( Structured Command )
更多精彩
- 更多技术博客,请移步 IT人才终生实训与职业进阶平台 - 实训在线
导览
- 使用结构化命令可以改变 shell 脚本的正常执行流程
-
if-then
语句是最基本的结构化命令,允许执行一个命令,并根据命令的输出情况决定后续输出 -
if-then-else
语句是if-then
语句的扩展版,可以将命令执行后的是否情况进行完整覆盖 -
if-then-elif-then
语句是if-then
语句的升级版,相当于把两个if-then
语句进行嵌套 -
if-then-elif-then-else
语句是if-then
语句的终极版,相当于在多个if-then
语句嵌套后再提供一个最坏情况下的缺省判断- 这其中的
elif-then
部分可以无限嵌套
- 这其中的
-
test
命令可以让if-then
语句实现条件判断,方括号( [ condition ] ) 是test
命令的简写版 -
双括号 可以实现覆盖
test
命令基本功能的前提下,进行更多的高级数学运算,例如val++
、!val
-
双方括号 可以实现覆盖
test
命令基本功能的前提下,进行更多的高级字符串比较,其实就是进行字符串的正则表达式匹配 -
case
命令可以代替嵌套过于复杂的if-then
语句,让语法逻辑更清晰明了
12.1 使用 if-then 语句
-
if-then
语句是最基本的结构化命令,基本语法如下- 如果
if
后的command
退出状态码是 0 ,则会执行then
后面的command
- 如果
if command
then
command
fi
-
写一个简单的例子演示一下,如下图
12.2 if-then-else 语句
-
if-then-else
语句是在if-then
语句不满足条件无法执行时,提供else
语句执行另外一部分命令,基本语法如下- 如果
if
的条件不满足,会执行else
后面的command
- 如果
if command
then
command
else
command
fi
-
写一个简单的例子演示一下,如下图
12.3 嵌套 if
-
if-then-elif-then
语句是在if-then
语句不满足条件,但又不想直接通过else
执行另一部分命令时,可以通过elif
再做一次判断,基本语法如下- 如果
if
的条件不满足,会再判断一次elif
的条件,满足则执行elif
后续then
中的command
,否则什么都不做
- 如果
if command
then
command
elif command
then
command
fi
-
if-then-elif-then
语句还可以和之前的else
做结合,最终写成if-then-elif-then-else
的版本 - 在一个完整的
if-then-elif-then-else
的语句中,if
和else
都只能出现一次,但elif
可以在中间出现无数次- 但过多的
if
结构嵌套会导致 shell 的逻辑判断非常混乱,所以不建议写这种链式操作
- 但过多的
- 写一个简单的例子演示一下,如下图
-
elif
中用到了后续会学到的条件判断,不用慌
-
12.4 test 命令
-
if-then
语句无法直接获取命令退出状态码之外的条件,但是可以通过test
命令实现这种需求 - 如果
test
命令列出的条件成立,test
命令就会返回退出状态码 0 -
test
命令和if-then
语句结合使用的语法如下
if test condition
then
command
fi
- 如果
test
命令后面不使用任何条件,默认会返回退出状态码 1 ,如下图
- 写一个简单的例子演示一下,如下图
- 当 user 不是空的时候,输出了
if-then
后面的语句 - 当 gender 是空的时候,输出了
else
后面的语句
- 当 user 不是空的时候,输出了
-
test
命令其实还提供了一种简写形式,语法如下- 使用一对中括号将测试条件包裹,就可以完美替代掉
test
命令的显式字符 - 需要注意的是,中括号与测试条件之间必须在首尾添加空格,这是语法强制性要求,不是规范性要求
- 使用一对中括号将测试条件包裹,就可以完美替代掉
if [ condition ]
then
command
fi
- 写一个简单的例子演示一下,如下图
- 测试的内容和上一个例子一样,只是把
test
命令换成了中括号,得到的结果是完全一致的
- 测试的内容和上一个例子一样,只是把
12.4.1 使用 test 命令进行数值比较
-
test
命令支持以下列表的数值比较形式-
需要注意的是,只能处理整数值,对于浮点数值处理不能
-
需要注意的是,只能处理整数值,对于浮点数值处理不能
-
写一个简单的例子演示一下,如下图
12.4.2 字符串比较
-
test
命令支持以下列表的字符串比较形式- 判断字符串是否相等、长度是否为 0 还比较实用
- 但是判断字符串的大小就不太实用,而且这个大小比较其实是顺序比较
- 不光是顺序比较,在
test
命令中直接使用大于号小于号还会导致被误判为 输出重定向 和 输入重定向 ,需要使用转义符才能避免这种误判 -
所以字符串的大小不止是不实用,还特别难用,这里就不演示了
-
写一个简单的例子演示一下,如下图
12.4.3 文件比较
-
test
命令支持以下列表的文件比较形式
12.4.3.1 使用 -d file 检查目录
- 使用
[ -d file ]
可以判断 file 是否存在,并且是目录,如下图
12.4.3.2 使用 -e file 检查对象是否存在
- 使用
[ -e file ]
可以判断 file 是否存在,如下图- 先通过
[ -e file ]
判断对象是否存在 - 如果对象存在,再通过
[ -d file ]
判断对象是否为目录,不是目录就是文件
- 先通过
12.4.3.3 使用 -f file 检查文件
- 使用
[ -f file ]
可以判断 file 是否为文件,如下图- 这个例子和上一个例子的区别就是把第二层判断从
[ -d file ]
改成了[ -f file ]
- 然后
then
和else
中的输出进行了对调,得到的结果是一样的
- 这个例子和上一个例子的区别就是把第二层判断从
12.4.3.4 使用 -r file 检查文件是否可读
- 使用
[ -r file ]
可以判断 file 是否存在,并且可读,如下图
12.4.3.5 使用 -s file 检查空文件
- 使用
[ -s file ]
可以判断 file 是否非空,对象不是空的就返回 0 ,否则返回 1 ,如下图
12.4.3.6 使用 -w file 检查文件是否可写
- 使用
[ -w file ]
可以判断 file 是否存在,并且可写,如下图
12.4.3.7 使用 -x file 检查文件是否可执行
- 使用
[ -x file ]
可以判断 file 是否存在,并且可执行,如下图
12.4.3.8 使用 -O file 检查文件所属用户关系
- 使用
[ -O file ]
可以判断 file 是否存在,并且是否属于当前执行脚本的用户,如下图- 注意这是大写字母
O
,而不是数字0
- 注意这是大写字母
12.4.3.9 使用 -G file 检查文件所属组关系
- 使用
[ -G file ]
可以判断 file 是否存在,并且 file 的默认组和当前用户的默认组是否相同,如下图- 需要注意的是,这里只会判断两者的默认组是否相同
- 如果 file 的默认组中当前用户是组成员,但并不是当前用户的默认组,那么检查结果返回的会是 0
12.4.3.10 使用 -nt 和 -ot 检查文件日期
- 使用
file1 -nt file2
可以检查 file1 是否比 file2 新 - 使用
file1 -ot file2
可以检查 file1 是否比 file2 旧 - 写一个简单的例子演示一下,如下图
- 需要注意的是,检查的是创建日期
-
还需要注意的是,这个比较不会自动判断比较对象是否存在
12.5 复合条件测试
-
if-then
语句后的条件支持两种形式的条件同时判断,形式如下- 用法就和 Java 或 JS 等编程语言中一样,不再赘述
[ condition ] && [ condition ]
[ condition ] || [ condition ]
-
写一个简单的例子演示一下,如下图
12.6 if-then 的高级特性
12.6.1 使用双括号计算数学表达式
- 在
if-then
语句中使用双括号后,可以在双括号中使用多个复杂的数学表达式,例如val++
、val--
、++val
、--val
、!val
- 这些参数对于使用过 Java 或 JS 等编程语言的来说肯定不陌生,但使用起来却不太一样
- 另外还有一些位运算符,例如
~
、&
、|
,不常用就不多做介绍
- 而且双括号并不局限于写在
if
后面的条件判断中,也可以在then
后面的输出中使用- 其实双括号就算不在 if 语句中,也可以直接使用
- 同时在双括号中对于大于、小于等操作不需要使用对应的
-gt
、-lt
操作符,可以直接使用>
、<
- 写一个简单的例子演示一下,如下图
- 在 Java 中,
num++
其实是num=num+1
- 但在 shell 中,想要实现
num=num+1
的效果必须是num2=num1++1
,如果直接写成num++
会报错
- 在 Java 中,
12.6.2 使用双方括号进行字符串处理
- 在双括号中可以实现的高级字符串处理,是指除了能实现
test
命令提供的所有特性外,还能实现 模式匹配( Pattern Matching )- 其实就是进行字符串的正则表达式匹配
- 不是所有的 shell 都支持双方括号
-
写一个简单的例子演示一下,如下图
12.7 case 命令
- 使用
case
命令可以实现复杂的嵌套if-then
语句的效果,但逻辑相对if-then
语句会更清晰,基本语法如下-
case
语句会将 variable 的值与in
后面的各种 pattern 进行比较,如何符合,则执行对应的 command - 如果所有的 pattern 都不符合,则执行最后星号中的 command
- 需要注意的是,如果一个条件后面有多个语句,并不是每个语句最后都需要使用 双分号( ;; ) ,而是只需要在该条件的最后一个语句使用即可
-
case variable in
pattern1 | pattern2 )
command1
command2;;
pattern3 )
command;;
* )
default command;;
esac
-
写一个简单的例子演示一下,如下图