【Linux 命令行与 shell 脚本编程大全】 12 使用结构化命令(if)

导览

  1. 使用结构化命令可以改变 shell 脚本的正常执行流程
  2. if-then 语句是最基本的结构化命令,允许执行一个命令,并根据命令的输出情况决定后续输出
  3. if-then-else 语句是 if-then 语句的扩展版,可以将命令执行后的是否情况进行完整覆盖
  4. if-then-elif-then 语句是 if-then 语句的升级版,相当于把两个 if-then 语句进行嵌套
  5. if-then-elif-then-else 语句是 if-then 语句的终极版,相当于在多个 if-then 语句嵌套后再提供一个最坏情况下的缺省判断
    • 这其中的 elif-then 部分可以无限嵌套
  6. test 命令可以让 if-then 语句实现条件判断,方括号( [ condition ] )test 命令的简写版
  7. 双括号 可以实现覆盖 test 命令基本功能的前提下,进行更多的高级数学运算,例如 val++!val
  8. 双方括号 可以实现覆盖 test 命令基本功能的前提下,进行更多的高级字符串比较,其实就是进行字符串的正则表达式匹配
  9. case 命令可以代替嵌套过于复杂的 if-then 语句,让语法逻辑更清晰明了

12.1 使用 if-then 语句

  1. if-then 语句是最基本的结构化命令,基本语法如下
    • 如果 if 后的 command 退出状态码是 0 ,则会执行 then 后面的 command
if command
then
  commands
fi

#或者
if command; then
 commands
fi
  1. 写一个简单的例子演示一下,如下图
image.png

12.2 if-then-else 语句

  1. if-then-else 语句是在 if-then 语句不满足条件无法执行时,提供 else 语句执行另外一部分命令,基本语法如下
    • 如果 if 的条件不满足,会执行 else 后面的 command
if command
then
  command
else
  command
fi

  1. 写一个简单的例子演示一下,如下图
[ttxie@41 part12]$ cat if_else.sh 
#!/bin/bash

user=NoSuchUser

if cat /etc/passwd | grep $user
then
  echo "如果IF 判断成功,会输出该语句"
else
  echo "如果IF 判断失败,会输出该语句"
fi
image.png

12.3 嵌套 if

  1. if-then-elif-then 语句是在 if-then 语句不满足条件,但又不想直接通过 else 执行另一部分命令时,可以通过 elif 再做一次判断,基本语法如下
    • 如果 if 的条件不满足,会再判断一次 elif 的条件,满足则执行 elif 后续 then 中的 command ,否则什么都不做
if command
then
  command
elif command
then
  command
fi

  1. if-then-elif-then 语句还可以和之前的 else 做结合,最终写成 if-then-elif-then-else 的版本
  2. 在一个完整的 if-then-elif-then-else 的语句中,ifelse 都只能出现一次,但 elif 可以在中间出现无数次
    • 但过多的 if 结构嵌套会导致 shell 的逻辑判断非常混乱,所以不建议写这种链式操作
  3. 写一个简单的例子演示一下,如下图
    • elif 中用到了后续会学到的条件判断,不用慌
    • 紧跟其后的else语句属于elif代码块,,他们并不属于之前的if-then代码块
[ttxie@41 part12]$ cat if-elif-else.sh 
#!/bin/bash

user=asinglelife
if cat /etc/passwd | grep $user
then
  echo "这句话不会被执行"
elif [ $user = $USER ]
then
  echo "提前用一下IF 判断语句"
else
  echo "紧跟其后的else语句属于elif代码块,,他们并不属于之前的if-then代码块"
fi

12.4 test 命令

  1. if-then 语句无法直接获取命令退出状态码之外的条件,但是可以通过 test 命令实现这种需求
  2. 如果 test 命令列出的条件成立,test 命令就会返回退出状态码 0
  3. test 命令和 if-then 语句结合使用的语法如下
if test condition
then
  command
fi

  1. 如果 test 命令后面不使用任何条件,默认会返回退出状态码 1 ,如下图

    image
  2. 写一个简单的例子演示一下,如下图

    • user 不是空的时候,输出了 if-then 后面的语句

    • gender 是空的时候,输出了 else 后面的语句

      image
  3. test 命令其实还提供了一种简写形式,语法如下

    • 使用一对中括号将测试条件包裹,就可以完美替代掉 test 命令的显式字符
    • 需要注意的是,中括号与测试条件之间必须在首尾添加空格,这是语法强制性要求,不是规范性要求
if [ condition ]
then
  command
fi

  1. 写一个简单的例子演示一下,如下图
    • 测试的内容和上一个例子一样,只是把 test 命令换成了中括号,得到的结果是完全一致的
[ttxie@41 part12]$ cat if-test-updata.sh
#!/bin/bash

user=asinglelife
gender=""

if [ $user ]
then
  echo "使用test,可以测试变量是否为空"
else
  echo "用户名是空的"
fi

if [ $gender ]
then
  echo "$user 的性别是$gender"
else
  echo "性别是空的"
fi

image.png

12.4.1 使用 test 命令进行数值比较

  1. test 命令支持以下列表的数值比较形式

    • 需要注意的是,只能处理整数值,对于浮点数值处理不能

      image
  2. 写一个简单的例子演示一下,如下图

    image

12.4.2 字符串比较

  1. test 命令支持以下列表的字符串比较形式

    • 判断字符串是否相等、长度是否为 0 还比较实用

    • 但是判断字符串的大小就不太实用,而且这个大小比较其实是顺序比较

    • 不光是顺序比较,在 test 命令中直接使用大于号小于号还会导致被误判为 输出重定向输入重定向 ,需要使用转义符才能避免这种误判

    • 所以字符串的大小不止是不实用,还特别难用,这里就不演示了

      image
  2. 写一个简单的例子演示一下,如下图

    image

12.4.3 文件比较

  1. test 命令支持以下列表的文件比较形式

    image

12.4.3.1 使用 -d file 检查目录

  1. 使用 [ -d file ] 可以判断 file 是否存在,并且是目录,如下图

    image

12.4.3.2 使用 -e file 检查对象是否存在

  1. 使用 [ -e file ] 可以判断 file 是否存在,如下图
    • 先通过 [ -e file ] 判断对象是否存在

    • 如果对象存在,再通过 [ -d file ] 判断对象是否为目录,不是目录就是文件

      image

12.4.3.3 使用 -f file 检查文件

  1. 使用 [ -f file ] 可以判断 file 是否为文件,如下图
    • 这个例子和上一个例子的区别就是把第二层判断从 [ -d file ] 改成了 [ -f file ]

    • 然后 thenelse 中的输出进行了对调,得到的结果是一样的

      image

12.4.3.4 使用 -r file 检查文件是否可读

  1. 使用 [ -r file ] 可以判断 file 是否存在,并且可读,如下图

    image

12.4.3.5 使用 -s file 检查空文件

  1. 使用 [ -s file ] 可以判断 file 是否非空,对象不是空的就返回 0 ,否则返回 1 ,如下图

    image

12.4.3.6 使用 -w file 检查文件是否可写

  1. 使用 [ -w file ] 可以判断 file 是否存在,并且可写,如下图

    image

12.4.3.7 使用 -x file 检查文件是否可执行

  1. 使用 [ -x file ] 可以判断 file 是否存在,并且可执行,如下图

    image

12.4.3.8 使用 -O file 检查文件所属用户关系

  1. 使用 [ -O file ] 可以判断 file 是否存在,并且是否属于当前执行脚本的用户,如下图
    • 注意这是大写字母 O ,而不是数字 0

      image

12.4.3.9 使用 -G file 检查文件所属组关系

  1. 使用 [ -G file ] 可以判断 file 是否存在,并且 file 的默认组和当前用户的默认组是否相同,如下图
    • 需要注意的是,这里只会判断两者的默认组是否相同

    • 如果 file 的默认组中当前用户是组成员,但并不是当前用户的默认组,那么检查结果返回的会是 0

      image

12.4.3.10 使用 -nt 和 -ot 检查文件日期

  1. 使用 file1 -nt file2 可以检查 file1 是否比 file2
  2. 使用 file1 -ot file2 可以检查 file1 是否比 file2
  3. 写一个简单的例子演示一下,如下图
    • 需要注意的是,检查的是创建日期

    • 还需要注意的是,这个比较不会自动判断比较对象是否存在

      image

12.5 复合条件测试

  1. if-then 语句后的条件支持两种形式的条件同时判断,形式如下
    • 用法就和 Java 或 JS 等编程语言中一样,不再赘述
[ condition ] && [ condition ]
[ condition ] || [ condition ]

  1. 写一个简单的例子演示一下,如下图

    image

12.6 if-then 的高级特性

12.6.1 使用双括号计算数学表达式

  1. if-then 语句中使用双括号后,可以在双括号中使用多个复杂的数学表达式,例如 val++val--++val--val!val
    • 这些参数对于使用过 Java 或 JS 等编程语言的来说肯定不陌生,但使用起来却不太一样
    • 另外还有一些位运算符,例如 ~&| ,不常用就不多做介绍
  2. 而且双括号并不局限于写在 if 后面的条件判断中,也可以在 then 后面的输出中使用
    • 其实双括号就算不在 if 语句中,也可以直接使用
  3. 同时在双括号中对于大于、小于等操作不需要使用对应的 -gt-lt 操作符,可以直接使用 ><
  4. 写一个简单的例子演示一下,如下图
    • 在 Java 中,num++ 其实是 num=num+1
    • 但在 shell 中,想要实现 num=num+1 的效果必须是 num2=num1++1 ,如果直接写成 num++ 会报错
[ttxie@41 part12]$ cat bracket.sh 
#!/bin/bash

num1=10

if (( $num1 >= 10  ))
then
   echo "现在num1的值是$num1"

   (( num2 = $num1 ++ 1 ))
   echo "num2的值=num1 +1,现在num2的值为$num2,num1的值为$num1"

fi

image.png

12.6.2 使用双方括号进行字符串处理

  1. 在双括号中可以实现的高级字符串处理,是指除了能实现 test 命令提供的所有特性外,还能实现 模式匹配( Pattern Matching )
    • 其实就是进行字符串的正则表达式匹配
    • 不是所有的 shell 都支持双方括号
  2. 写一个简单的例子演示一下,如下图
[ttxie@41 part12]$ cat if-square-bracket.sh
#!/bin/bash

if [[ $USER == tt*  ]]
then
   echo "hello $USER"
else
   echo "I do not know you"
fi
image.png

12.7 case 命令

  1. 使用 case 命令可以实现复杂的嵌套 if-then 语句的效果,但逻辑相对 if-then 语句会更清晰,基本语法如下
    • case 语句会将 variable 的值与 in 后面的各种 pattern 进行比较,如何符合,则执行对应的 command
    • 如果所有的 pattern 都不符合,则执行最后星号中的 command
    • 需要注意的是,如果一个条件后面有多个语句,并不是每个语句最后都需要使用 双分号( ;; ) ,而是只需要在该条件的最后一个语句使用即可
case variable in
pattern1 | pattern2 ) 
  command1
  command2;;
pattern3 ) 
  command;;
* ) 
  default command;;
esac

  1. 写一个简单的例子演示一下,如下图
[ttxie@41 part12]$ cat case.sh 
#!/bin/bash

echo "当前用户为:$USER"

case $USER in
rich | barbara)
 echo "这个用户是rich or barbara";;
ttxie)
 echo "这个用户是ttxie";;
*)
 echo "谁也不是";;
esac
image.png

部分内容转载来自:作者asing1elife 链接:https://www.jianshu.com/p/4915279d3c2e

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容