一、if-then语句

shell中最基本的结构化命令是if-then语句:

if command
thencommands
fi

如果你在用其他编程语言的if-then语句,这种形式可能会让你有点困惑。

在其他编程语言中,if语句之后的对象是一个等式,这个等式的求值结果为TRUE或FALSE。

但bash shell的if语句并不是这么做的。bash shell的if语句会运行if后面的那个命令。

如果该命令的退出状态码(参见第11章)是0(该命令成功运行),位于then部分的命令就会被执行。

如果该命令的退出状态码是其他值,then部分的命令就不会被执行,bash shell会继续执行脚本中的下一个命令。

fi语句用来表示if-then语句到此结束。

例如:

#!/bin/bash
# testing the if statement
if pwd
thenecho "It worked"
fi

pwd命令成功运行,屏幕会打印“It worked”。

否则:

#!/bin/bash
# testing a bad command
if IamNotaCommand
thenecho "It worked"
fiecho "We are outside the if statement"

乱码的命令不执行,返回正数,为错误值,不执行then后的语句,因此输出“We are outside the if statement”。

二、if-then-else语句

在if-then语句中,不管命令是否成功执行,你都只有一种选择。如果命令返回一个非零退出状态码,bash shell会继续执行脚本中的下一条命令。在这种情况下,如果能够执行另一组命令就好了。这正是if-then-else语句的作用:

if command
thencommands
elsecommands
fi

例如:

#!/bin/bash
# testing the else section
testuser=NoSuchUser
if grep $testuser /etc/passwd
thenecho "The bash files for user $testuser are:"ls -a /home/$testuser/.b*
elseecho "The user $testuser does not exist on this system."
fi

if语句行使用grep命令在/etc/passwd文件中查找某个用户名当前是否在系统上使用。如果有
用户使用了那个登录名,脚本会显示一些文本信息并列出该用户HOME目录的bash文件。

显然“NoSuchUser”并不是我的用户名,因此执行else后的内容,输出“The user NoSuchUser does not exist on this system”。

三、嵌套if-then

有时你需要检查脚本代码中的多种条件。对此,可以使用嵌套的if-then语句。

要检查/etc/passwd文件中是否存在某个用户名以及该用户的目录是否尚在,可以使用嵌套的
if-then语句。嵌套的if-then语句位于主if-then-else语句的else代码块中。

例如,要检查/etc/passwd文件中是否存在某个用户名以及该用户的目录是否尚在,可以使用嵌套的if-then语句。嵌套的if-then语句位于主if-then-else语句的else代码块中。

#!/bin/bash
# Testing nested ifs
#
testuser=NoSuchUser
#
if grep $testuser /etc/passwd
thenecho "The user $testuser exists on this system."
elseecho "The user $testuser does not exist on this system."if ls -d /home/$testuser/thenecho "However, $testuser has a directory."fi
fi

这个脚本准确无误地发现,尽管登录名已经从/etc/passwd中删除了,但是该用户的目录仍然存在。

在脚本中使用这种嵌套if-then语句的问题在于代码不易阅读,很难理清逻辑流程。

可以使用else部分的另一种形式:elif。

这样就不用再书写多个if-then语句了。elif使用另一个if-then语句延续else部分。

if command1
thencommands
elif command2
thenmore commands
fi

elif语句行提供了另一个要测试的命令,这类似于原始的if语句行。如果elif后命令的退出状态码是0,则bash会执行第二个then语句部分的命令。使用这种嵌套方法,代码更清晰,逻辑更易懂。

更进一步,让脚本检查拥有目录的不存在用户以及没有拥有目录的不存在用户:

#!/bin/bash
# Testing nested ifs - use elif & else
#
testuser=NoSuchUser
#
if grep $testuser /etc/passwd
thenecho "The user $testuser exists on this system."
#
elif ls -d /home/$testuser
thenecho "The user $testuser does not exist on this system."echo "However, $testuser has a directory."
#
elseecho "The user $testuser does not exist on this system."echo "And, $testuser does not have a directory."
fi

这段代码检查所给用户是否在此系统中,如果有,则输出“The user $testuser exists on this system”,并列出其目录;

如果没有但登录过,则输出“The user $testuser does not exist on this system,However, $testuser has a directory”;

如果这个用户从没在服务器存在过,则输出“The user $testuser does not exist on this system,And, $testuser does not have a directory”。

四、test语句

if-then语句有一个限制,那就是它只能检测退出码。因此,我们需要另一个命令——test,来检测退出码之外的条件。

test condition

与if-then联用时,它是这样的:

if test condition
thencommands
fi

如果不写test命令的condition部分,它会以非零的退出状态码退出,并执行else语句块。

另外,bash shell提供了“[ ]”,无需在if-then语句中声明test命令,这方便了很多。

注意,第一个方括号之后和第二个方括号之前必须加上一个空格,否则就会报错。

if [ condition ]
thencommands
fi

test命令可以判断三类条件:数值比较、字符串比较、文件比较

(1)数值比较

表1 test命令的数值比较功能
比 较 描 述
n1 -eq n2 检查n1是否与n2相等
n1 -ge n2 检查n1是否大于或等于n2
n1 -gt n2 检查n1是否大于n2
n1 -le n2 检查n1是否小于或等于n2
n1 -lt n2 检查n1是否小于n2
n1 -ne n2 检查n1是否不等于n2

例如:

#!/bin/bash
# Using numeric test evaluations
value1=10
value2=11
#
if [ $value1 -gt 5 ]
thenecho "The test value $value1 is greater than 5"
fi
#
if [ $value1 -eq $value2 ]
thenecho "The values are equal"
elseecho "The values are different"
fi

别忘了,shell只能处理整数,所以不要比较浮点数!

(2)字符串比较

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

注意,“<”“>”需要前加“\”转义,否则会被当做重定向!

(3)文件比较

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

五、复合条件测试

if-then语句允许你使用布尔逻辑来组合测试。有两种布尔运算符可用:
(1) [ condition1 ] && [ condition2 ]
(2)[ condition1 ] || [ condition2 ]

第一种布尔运算使用AND布尔运算符来组合两个条件。要让then部分的命令执行,两个条件都必须满足。

第二种布尔运算使用OR布尔运算符来组合两个条件。如果任意条件为TRUE,then部分的命令就会执行。

六、if-then高级特性

1、双括号

(( expression ))

双括号命令允许你在比较过程中使用高级数学表达式。但shell数学表达是弱项,平日也少用shell计算,所以这段略过。

2、双方括号

[[ expression ]]

双方括号里的expression使用了test命令中采用的标准字符串比较。但它提供了test命令未提供的另一个特性——模式匹配。

在模式匹配中,可以定义一个正则表达式来匹配字符串值。

#!/bin/bash
# using pattern matching
#
if [[ $USER == r* ]]
then
echo "Hello $USER"
else
echo "Sorry, I do not know you"
fi

在上面的脚本中,我们使用了双等号(==)。双等号将右边的字符串(r*)视为一个模式,并应用模式匹配规则。双方括号命令$USER环境变量进行匹配,看它是否以字母r开头。如果是的话,比较通过,shell会执行then部分的命令。

七、case命令

你会经常发现自己在尝试计算一个变量的值,在一组可能的值中寻找特定值。

在这种情形下,你不得不写出很长的if-then-else语句,就像下面这样。

#!/bin/bash
# looking for a possible value
#
if [ $USER = "rich" ]
thenecho "Welcome $USER"echo "Please enjoy your visit"
elif [ $USER = "barbara" ]
thenecho "Welcome $USER"echo "Please enjoy your visit"
elif [ $USER = "testing" ]
thenecho "Special testing account"
elif [ $USER = "jessica" ]
thenecho "Do not forget to logout when you're done"
elseecho "Sorry, you are not allowed here"
fi

学会case命令后,就不需要再写出所有的elif语句来不停地检查同一个变量的值了。

case命令会采用列表格式来检查单个变量的多个值。

case variable in
pattern1 | pattern2) commands1;;
pattern3) commands2;;
*) default commands;;
esac

case命令会将指定的变量与不同模式进行比较。如果变量和模式是匹配的,那么shell会执行为模式指定的命令。可以通过竖线操作符在一行中分隔出多个模式模式。星号会捕获所有与已知模式不匹配的值。

我们可把上述if-the-else语句简化为:

#!/bin/bash
# using the case command
#
case $USER in
rich | barbara)echo "Welcome, $USER"echo "Please enjoy your visit";;
testing)echo "Special testing account";;
jessica)echo "Do not forget to log off when you're done";;
*)echo "Sorry, you are not allowed here";;
esac

参考资料:《linux命令行与shell脚本编程大全.第三版》

生物信息学缘起——linux篇(五)if-then-else命令相关推荐

  1. 生物信息学缘起——linux篇(六)for和while循环

    一.for循环语句 在linux中,for循环语句的逻辑和使用方法与其他编程语言类似,允许你创建一个遍历一系列值的循环,每次迭代都使用其中一个值来执行已定义好的一组命令. for var in lis ...

  2. 生物信息学缘起——linux篇(四):shell编程

    一.Hello World! 让我们先从最简单的编程开始: # 创建一个Helloword.sh 文件 touch Helloword.sh# 编辑Helloword.sh 文件 vim Hellow ...

  3. Linux 的五个关机重启命令

    一.Linux 的五个关机重启命令 1.shutdown 2.poweroff 3.init 4.reboot 5.halt 二.具体说明 在linux下一些常用的关机/重启命令有shutdown.h ...

  4. 软件测试基础篇五App之adb命令

    命令优势:效率高 面试会问 工具的本质也是调用命令 解决工具的能力边界 ADB可以用来安装卸载软件.管理安卓系统软件.启动测试.抓取操作日志等 一.常用命令 1.查看已连接的设备列表:adb devi ...

  5. 为啥linux分区是nvme0n1,NAS 篇五:尝试达成最终目标: 黑裙+万兆网卡+Nvme 存储空间的实现与测试...

    NAS 篇五:尝试达成最终目标: 黑裙+万兆网卡+Nvme 存储空间的实现与测试 2020-01-18 18:49:23 46点赞 248收藏 80评论 创作立场声明:1. 本系列文章讨论NAS与局域 ...

  6. 硬盘底座linux,微客智品 篇五十二:机械硬盘如何安放?用奥睿科单盘位移动硬盘底座助力新玩法...

    微客智品 篇五十二:机械硬盘如何安放?用奥睿科单盘位移动硬盘底座助力新玩法 2020-01-07 15:36:58 1点赞 10收藏 30评论 随着新一代M.2硬盘的流行与普及,3.5寸机械硬盘愈发变 ...

  7. ds存储查看 linux,我的NAS我的地盘 篇五:群晖NAS软件介绍与应用之DS Audio篇

    我的NAS我的地盘 篇五:群晖NAS软件介绍与应用之DS Audio篇 2019-03-01 14:11:20 35点赞 567收藏 51评论 前言 继续昨天的话题,前文介绍了群晖下的视频播放管理器D ...

  8. Linux篇:Shell脚本实现Gitlab双备份

    01 前言 最近成功从架构组拿到了Gitlab的管理权限,第一件事就是想着如何备份,以防数据丢失背大锅,于是在网上搜索一番,发现一段非常赞的备份脚本,记录照着操作一下: 参考文章:https://bl ...

  9. 黑群辉安装php,黑群晖从装机到使用全过程 篇五:群晖安装VirtualBox虚拟机

    黑群晖从装机到使用全过程 篇五:群晖安装VirtualBox虚拟机 2017-10-13 21:29:39 33点赞 312收藏 28评论 经常喜欢折腾电脑的童鞋一定知道虚拟机,在自己的电脑上可以安装 ...

最新文章

  1. mybatis开发dao的方法——(三)
  2. QML编程之旅 -- 事件处理
  3. Docker基本组成 和 基本命令
  4. 格力:今日投放12万只格力口罩 明日起增至16万只
  5. 读后感:软件测试经验与教训
  6. jquery ajax 访问 mysql_使用ajax+jquery+php访问mysql数据库,并且达到不跳转页面的效果。。。...
  7. POJ3250 Bad Hair Day【单调递减队列+堆栈】
  8. 持续集成~Jenkins构建GitHub项目的实现
  9. 【STM32】STM32CubeMX使用FreeRTOS教程1----定时器学习
  10. 电脑打开应用程序提示配置系统未能初始化--解决方案
  11. html span 文字垂直居中,p标签中的span标签文字垂直居中对齐
  12. 免费公共DNS服务器大全
  13. 车联网智能终端GB/T 32960国标协议规范 、国标新能源车联网终端GB/T32960标准T-BOX应用
  14. EMC 电路设计基础
  15. 夹缝中的垂直母婴电商贝莱优品们:生存之道怎么挖?
  16. HBuilderX初次使用
  17. 跟潭州学院的强子老师学习网络爬虫---爬取全书网
  18. 矩阵相似,矩阵合同,矩阵等价概念总结
  19. 信贷客户调查中最需关注的十个方面(附经典案例解析)
  20. 有限差分法电磁场matlab,有限差分法的分析电磁场边值问题(定稿).doc

热门文章

  1. pptp的 服务器位置,pptp 服务器地址问题
  2. 基于OpenWrt的PPTP服务器
  3. 网页显示的几种常用字体
  4. 【开源教程10】疯壳·开源蓝牙心率防水运动手环-蓝牙 BLE 收发
  5. 后缀数组——height数组
  6. 老家养牛比你在外面漂着舒服多了?
  7. 华为智能摄像头pro鸿蒙系统,内置鸿蒙系统,华为生态产品海雀智能摄像头Pro体验...
  8. sed grep awk之间比较
  9. 感觉最智能的工作,偏偏最人工——元旦的致命来电
  10. 基于springboot+vue的养老院管理系统