掌握Shell脚本的if语句,让你的代码更加精准和高效

news2025/3/3 19:28:43

在这里插入图片描述

前言

大家好,我是沐风晓月,本文首发于csdn, 作者: 我是沐风晓月。 文章收录于 我是沐风晓月csdn专栏 【系统架构实战】专栏中的【shell脚本入门到精通】专栏。

本专栏从零基础带你层层深入,学会shell脚本,不是梦。

🏠个人主页:我是沐风晓月
🧑个人简介:大家好,我是沐风晓月,双一流院校计算机专业,阿里云博客专家
😉😉 💕 座右铭: 先努力成长自己,再帮助更多的人,一起加油进步
🍺🍺🍺 💕欢迎大家:这里是CSDN,我总结知识的地方,喜欢的话请三连,有问题请私信😘

文章目录

  • 前言
  • 一. if条件判断语句
    • 1.1 什么是if条件判断语句
    • 1.2 常用的测试操作符
    • 1.3 if条件判断语句的语法
  • 二. if语句常见案例
    • 2.1 判断系统目录是否存在(if单分支脚本)
    • 2.2 比较两个整数大小(if双分支脚本)
    • 2.3 判断年龄段(if多分支脚本)
  • 三. 拓展
    • 3.1 shell编程中各种括号的对比
    • 3.2 shell脚本中各种引号的对比
  • 总结

一. if条件判断语句

通常以if开头,fi结尾。也可加入else或者elif进行多条件的判断。

1.1 什么是if条件判断语句

if条件判断语句用于根据某些条件来决定是否执行一段代码块;常用的条件有很多,比如命令是否执行成功,可以用 $? 来判断。

而这种使用$?判断的结果无非有两个,一个是执行成功,一个是没有执行成功。 那我们就可以基于这两个条件来加在特定条件下想要执行的命令。

1.2 常用的测试操作符

    1. 文件测试操作

我们常见的测试工具-test命令,这个可以对特定的条件进行测试,并根据返回结果来判断条件是否成立。

语法:

格式一: test 操作符 表达式
 
 格式二: [ 操作符 表达式 ]  

常用的文件测试符:

操作符作用
-d测试文件是否为目录文件(Directory)
-f测试文件是否为普通文件(File)
-e测试目录或文件是否存在(Exist)
-s判断文件是否为存字且为非空文件
-N判断文件从上一次被读取之后是否被修改过
-a测试目录或文件是否存在(Exist)建议使用-e,-a可能不准确
-r测试当前用户是否有权限读取(Read)
-w测试当前用户是否有权限写入(Write)
-x测试当前用户是否有权限执行(eXcute)
-L测试是否为符号链接(软链接文件)
-nt判断文件A是否比文件B新
-ot判断文件A是否比文件B旧
-ef判断两个文件是否为同一文件。可用于硬链接,主要判断两个文件是否指向同一个inode。

案例一,判断/root/是否为目录,且输出它的状态码:

[root@mufeng ~]# test -d /root/ && echo $?
0

可以看到如果返回结果为0,说明root是目录

反之返回结果不为零,就不是目录

[root@mufeng ~]# test -d a.txt  ; echo $?
1

这里使用的&& 和;有什么区别?

其实除了&&和; 还有 ||,具体的区别如下:

  • &&: 逻辑与(and)

当使用 && 分隔两个命令时,如果第一个命令执行成功(返回值为 0),则会执行第二个命令。如果第一个命令执行失败(返回值非 0),则第二个命令不会执行。

  • ; 表示顺序执行

当使用 ; 分隔两个命令时,无论第一个命令执行成功与否,都会执行第二个命令。

  • || 逻辑或(or)

当使用 || 分隔两个命令时,如果第一个命令执行失败(返回值非 0),则会执行第二个命令。如果第一个命令执行成功(返回值为 0),则第二个命令不会执行

综上所述,三个命令分隔符的区别如下:

  • &&:只有前一个命令执行成功时,才会执行后一个命令。
  • ;:无论前一个命令执行成功与否,都会执行后一个命令。
  • ||:只有前一个命令执行失败时,才会执行后一个命令。

案例二: 使用文件测试符来判断

[root@mufeng ~]# [ -d /root/ ];echo $?
0
[root@mufeng ~]# [ -f /root/ ];echo $?
1
[root@mufeng ~]# 

这个时候没有使用test,其实效果是一样,只不过这里要用[]来框起来。

    1. 整数测试

整数之间也可以比较,整数之间的比较使用的操作符如下:

操作符含义
-eq等于(Equal)
-ne不等于(Not Equal)
-gt大于(Greater Than)
-lt小于(Lesser Than)
-le小于或等于(Lesser or Equal)
-ge大于或等于(Greater or Equal)

使用的语法:

[  整数变量1  操作符  整数变量2  ] 
 ​
 test 整数变量1  操作符  整数变量2

案例一: 测试3大于5

[root@mufeng ~]# [ 3 -gt 5 ]; echo $?
1
# 使用变量的形式
[root@mufeng ~]# a=3
[root@mufeng ~]# b=5

[root@mufeng ~]# [ $a -gt $b ];echo $?
1
[root@mufeng ~]# 

案例二 查询当前目录下的文件数是否小于100,如果小于则提示

[root@mufeng ~]# test `ls|wc -l` -lt 100 && echo "文件数小于100"

文件数小于100
    1. 字符串测试
      字符串的测试,不能够使用 le等等参数,那些参数只用于数字,那字符串的对比测试是如何来做呢?
操作符作用
=字符串内容相同
!=字符串内容不同,! 号表示相反的意思
-z字符串内容为空
-n字符是否存在

字符比较的语法格式:

 [ "字符串1"  =  "字符串2"  ]   //测试字符串1和字符串2的内容是否相同
 [ "字符串1" !=  "字符串2”  ]   //测试字符串1和字符串2的内容是否不同
 [ -z "字符串" ]    //测试字符串是否为空,或者指定的变量是否为空值。(测试字符串的长度是否为零)
 [ -n "字符串" ]    //测试字符串是否存在,即是否不为空。(测试字符串的长度是否非零)

-n不为空这里,我们可以用来判断对方输入的密码长度是否为空

思考: -z 和-n的区别?

在 shell 脚本中,-z 和 -n 是用于测试字符串长度的条件测试操作符。

-z 字符串 返回真(即退出状态为 0),如果字符串的长度为零。

-n 字符串 返回真(即退出状态为 0),如果字符串的长度非零。

所以,区别在于它们检查字符串长度的条件不同。

如果你想测试一个字符串是否为空,使用 -z;

如果你想测试一个字符串是否非空,使用 -n。

案例一: 判断用户输入的密码是否为空

[root@mufeng ~]# vim passwd.sh
[root@mufeng ~]# chmod +x passwd.sh 
[root@mufeng ~]# ./passwd.sh 
请输入你的密码:
当前未输入任何内容
[root@mufeng ~]# cat passwd.sh 
#!/bin/bash
read -p "请输入你的密码:" passwd

[ -z $passwd ]  && echo "当前未输入任何内容"

案例二: 判断两个字符串是否相等

[root@mufeng ~]# cat passwd.sh 
#!/bin/bash
sth=adbd
read -p "请输入你的密码:" passwd

[ $sth = $passwd ]  && echo "当前密码符合要求"
[root@mufeng ~]# ./passwd.sh 
请输入你的密码:adbd
当前密码符合要求
[root@mufeng ~]# 

这里我们使用的read 获取键盘输入,所获取到的一定是个字符串,但有时候我们直接定义的一些参数或者截取的参数,无法判断是字符串的时候,需要加 ""才能进行字符串的判断。

    1. 逻辑运算符

逻辑测试用于连接多个测试条件,并返回整个表达式的值。 逻辑测试主要有"逻辑与",“逻辑或”,"逻辑否"三种。

常见的逻辑运算符:

  • -a或&& :逻辑与,“而且”的意思,全真才为真。

  • -o或|| :逻辑或,“或者”的意思,一真即为真。

  • ! :逻辑否。

在上面的案例中,其实我们已经用到了比如 &&

比如我们可以这么用:


[root@mufeng ~]# [ 1 -lt 2 ] && [ 1 -gt 4 ] ;echo $?
1

这里的意思就是 1 小于2 ,并且1 大于4, 最终输出结果为 1, 也就是不成立。

但如果用 ||就不一样了

[root@mufeng ~]# [ 1 -lt 2 ] || [ 1 -gt 4 ] ;echo $?
0

这两个式子只要有一个成立即可。

1.3 if条件判断语句的语法

  1. 单分支语句
第一种语法:
if <条件表达式>
then
    指令
fi

第二种语法:推荐使用!
if <条件表达式>;then
    指令
fi

上文中的“<条件表达式>”位置部分,可以使用test、[]、[[]]、(())等条件表达式
备注:

  • if与条件表达式之间要有空格
  • [ ]与判断条件之间也必须有空格
  • ;前不能有空格
  • 以fi结尾,表示if语句的结束
  1. 双分支语句
if <条件表达式>
  then
    指令
  else
    指令
fi

例如:

if [ 家里是否有吃的 ]

  then
  
     我们在家吃晚饭
     
  else
  
     我们去饭馆就餐
     
fi
  1. 多分支语句
if <条件表达式1>; then
      指令1
elif <条件表达式2>; then
      指令2
elif <条件表达式3>; then
      指令3
.......
else
       指令语句
fi

二. if语句常见案例

2.1 判断系统目录是否存在(if单分支脚本)

#!/bin/bash
#2023-03-09 21:44:53
#By author mufeng
#Judge DIR or Files
#############################

if [ ! -d /tmp/mufeng/ ];then   
#判断mufeng目录是否存在,如果不存在,就创建mufeng目录
    mkdir -p /tmp/mufeng/
fi

运行结果:

[root@mufeng shell]# ll -d /tmp/mufeng/ 
ls: 无法访问/tmp/mufeng/: 没有那个文件或目录
[root@mufeng shell]# bash if_dir.sh 
[root@mufeng shell]# ll -d /tmp/mufeng/
drwxr-xr-x 2 root root 6 3月   9 21:53 /tmp/mufeng/

2.2 比较两个整数大小(if双分支脚本)

#!/bin/bash
#2023-03-09 21:59:10
#By author mufeng
#Judge Number Size
#############################

read -p "请输入第一个整数: " NUM1
read -p "请输入第二个整数: " NUM2
if (($NUM1 > $NUM2));then
    echo The $NUM1 greate than $NUM2.
else
    echo The $NUM1 less than $NUM2.
fi


运行结果:

[root@mufeng shell]# bash if_number.sh 
请输入第一个整数: 56
请输入第二个整数: 12
The 56 greate than 12.
[root@mufeng shell]# 

2.3 判断年龄段(if多分支脚本)


#!/bin/bash
#2023-03-09 22:38:07
#By author mufeng
#Judge age
#############################

read -p "请输入你的年龄: " age

if (($age < 8));then
    printf "儿童\n"
elif (($age >= 8 && $age< 18));then
    printf "少年\n"
elif (($age >= 18 && $age < 26));then
    printf "青年\n"
elif (($age >= 26 && $age < 40));then
    printf "壮年\n"
elif (($age >= 40 && $age < 60));then
    printf "中老年\n"
else
    printf "老年\n"
fi

运行结果:

[root@mufeng shell]# bash if_age.sh 
请输入你的年龄: 3
儿童
[root@mufeng shell]# bash if_age.sh 
请输入你的年龄: 56
中老年
[root@mufeng shell]# bash if_age.sh 
请输入你的年龄: 12
少年
[root@mufeng shell]# bash if_age.sh 
请输入你的年龄: 99
老年
[root@mufeng shell]# bash if_age.sh 
请输入你的年龄: 38
壮年

三. 拓展

3.1 shell编程中各种括号的对比

Shell编程中,尤其是使用if语句时,经常会使用()、(())、[]、[[]]、{}等括号,我们来对比下:

  • ( )用于多个命令组、命令替换、初始化数组,多用于SHELL命令组,
    例如:MO=(mo1 mo2 mo3),其中括号左右不保留空格;

  • (( ))整数扩展、运算符、重定义变量值,算术运算比较,例如:((i++))、((i<=100)),
    其中括号左右不保留空格;

  • [ ] bash内部命令,[ ]与test是等同的,正则字符范围、引用数组元素编号,
    不支持±*/数学运算符,逻辑测试使用-a、-o,
    通常用于字符串比较、整数比较以及数组索引,其中括号左右要保留空格;

  • [[ ]]bash程序语言的关键字,不是一个命令,[[ ]]结构比[ ]结构更加通用,
    不支持±*/数学运算符,逻辑测试使用&&、||,通常用于字符串比较、逻辑运算符等,
    其中括号左右要保留空格;

  • {}主要用于命令集合或者范围,例如mkdir -p /data/201{7,8}/,其中括号左右不保留空格。

3.2 shell脚本中各种引号的对比

Shell编程中,不仅会是使用变量,还经常会使用$、\、单引号、双引号、反引号等符号。
如下为几种符号简单区别对比:

  • $主要用于引用变量值,例如定义变量MF=mufeng,引用时,需要用 $MF;

  • \反斜杠,主要是用于对特定的字符实现转义,保留原有意义,例如echo “$MF”结果会打印$MF,而不会打印mufeng;

  • ''单引号 ,单引号又称为强引,不具有变量置换的功能,所有的任意字符还原为字面意义,实现屏蔽Shell元字符的功能;

  • "",双引号又称为弱引,具有变量置换的功能,保留$(使用变量前导符), (转义符), `(反向引号)元字符的功能;

  • 反向引号(``),反引号,位于键盘Tab键上面一行的键,用作命令替换(相当于$(…))。

举例:

[root@mufeng shell]# MF=mufeng

[root@mufeng shell]# echo $MF
mufeng

[root@mufeng shell]# echo \$MF
$MF

[root@mufeng shell]# echo hostname
hostname

[root@mufeng shell]# echo '$hostname'
$hostname

[root@mufeng shell]# echo `hostname`
mufeng

[root@mufeng shell]# echo $(hostname)
mufeng

总结

💕 好啦,这就是今天要分享给大家的全部内容了,我们下期再见!
💕 博客主页:mufeng.blog.csdn.net
💕 本文由沐风晓月原创,首发于CSDN博客
💕 全力以赴,持续学习,不负如来不负卿

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/404551.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

核心系统国产平台迁移验证

核心系统国产平台迁移验证 摘要&#xff1a;信息技术应用创新&#xff0c;旨在实现信息技术领域的自主可控&#xff0c;保障国家信息安全。金融领域又是关系国家经济命脉的行业&#xff0c;而对核心交易系统的信息技术应用创新是交易所未来将要面临的重大挑战。为了推进国产化进…

云数据库RDS介绍

RDS介绍 关系型数据库&#xff08;relational database service&#xff0c;简称RDS&#xff09;&#xff0c;是一种可靠、可弹性伸缩的在线数据库服务。 1&#xff09;基于分布式文件系统和SSD盘高性能存储 2&#xff09;支持MySQL、SQL Server、PostgreSQL、MariaDB TX引擎 …

原来不用控制台,也可以轻松调试CSS呀

Ⅰ. 作用 用于调试CSS , 比控制台添更加方便&#xff0c;不需要寻找 &#xff1b;边添加样式&#xff0c;边可以查看效果&#xff0c;适合初学者对CSS 的理解和学习&#xff1b; Ⅱ. 快速实现&#xff08;两边&#xff09; ① 显示这个样式眶 给 head 和 style 标签添加一个…

YOLOS学习记录

在前面&#xff0c;博主已经完成了YOLOS项目的部署与调试任务&#xff0c;并在博主自己构造的数据集上进行了实验&#xff0c;实验结果表明效果并不显著&#xff0c;其实这一点并不意外&#xff0c;反而是在情理之中。众所周知&#xff0c;Transformer一直以来作为NLP领域的带头…

独立开发者案例:每周4h月入数万刀;国家数据局与时代红利;创业前先买个域名;工程师成长最重要的是什么 | ShowMeAI周刊

这是ShowMeAI周刊的第6期。聚焦AI领域本周热点&#xff0c;及其在各圈层泛起的涟漪&#xff1b;关注AI技术进步&#xff0c;并提供我们的商业洞察。欢迎关注与订阅&#xff01;&#x1f440;日报合辑 ⌛ 独立开发者案例&#xff1a;每周只工作4小时&#xff0c;独立开发者打造月…

Docker nginx安装使用

拉取镜像$ docker pull nginx默认会拉取仓库名为nginx&#xff0c;tag为latest的镜像。挂载nginx.conf文件首次启动nginx容器考虑到后面维护nginx配置文件nginx.conf的成本&#xff0c;这里采用docker 数据卷的技术&#xff0c;即将docker中的nginx.conf配置文件挂载到宿主机当…

嵌入式学习笔记——STM32的USART通信概述

文章目录前言常用通信协议分类及其特征介绍通信协议通信协议分类1.同步异步通信2.全双工/半双工/单工3.现场总线/板级总线4. 串行/并行通信5. 有线通信、无线通信STM32通信协议的配置方式使用通信协议控制器实现使用IO口模拟的方式实现STM32串口通信概述什么是串口通信STM32F40…

# YOLOv8测试(1)

YOLOv8测试&#xff08;1&#xff09;1. 训练最简流程1.1 安装包1.2 训练demo1.3 验证参考文献资料鉴于网络上的太多教程&#xff0c;都太过繁琐了。其实之前也用过YOLOv2 v3版本&#xff0c;但很久没用&#xff0c;找了一圈教程多少有坑&#xff0c;想想还是自己整理一版吧。花…

测开:vue高级特性

vue官网地址&#xff1a; Vue.js - 渐进式 JavaScript 框架 | Vue.js 上一章节&#xff1a; 测开&#xff1a;vue基本语法_做测试的喵酱的博客-CSDN博客 一、vue事件修饰符 1.1 stop: 阻止事件冒泡 事件冒泡&#xff1a;子元素触发某个事件之后&#xff0c;会依次将这个事…

用DQN实现Atari game(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 强化学习研究的是Agent和环境交互中如何学习最优策略&#xff0c;以获得最大收益。Agent需要能够观察环境(observe)所处的状态&…

组播IP 映射 组播MAC

组播IP地址与组播MAC地址之间的换算方法与例子 1、在IP分类中&#xff0c;D类IP地址用于组播MAC。 2、在TCP/IP中&#xff0c;最常用的v4组播MAC地址的前24位固定为01005e&#xff0c;第25位固定为0&#xff0c;后23位由IP地址的后23位复制得出。 3、在D类组播IP中有5位未用&a…

Spark-行动算子

1、reduce&#xff08;聚合&#xff09; 2、collect&#xff08;采集&#xff09; 3、count &#xff08;统计&#xff09; 4、first 5、take 6、takeOrdered 7、aggregate 8、fold 9、countByKey 10、countByValue 11、save 算子 12、foreach 算子总结 所谓行…

java编程----继承

文章目录内存管理继承super向上造型内存管理 编写的xxx.java源码&#xff0c;编译为xxx.class字节码&#xff0c;由JVM&#xff08;java解释器&#xff09;来执行&#xff0c;JVM来对接不同的操作系统&#xff0c;实现一次编写&#xff0c;到处执行&#xff1b;JVM向操作系统申…

王朝游戏源码服务端与客户端搭建(基于nodejs与cocoscreator)

成功效果:搭建步骤:安装centos7 64 2009版本操作系统下载并解压mongodb,redis,nodejs3.复制游戏服务与网站服务程序到服务器4.编译nodejsnodejs编译并安装成功后验证5.配置并启动mongodb数据库mongodb.conf配置文件内容:dbpath/home/dev/mongodb/db logpath/home/dev/mongodb/l…

八、发布确认高级

在生产环境中由于一些不明原因&#xff0c;导致 rabbitmq 重启&#xff0c;在 RabbitMQ 重启期间生产者消息投递失败&#xff0c;导致消息丢失&#xff0c;需要手动处理和恢复 如何才能进行 RabbitMQ 的消息可靠投递呢&#xff1f;特别是在这样比较极端的情况&#xff0c;Rabb…

20230311给Ubuntu18.04下的GTX1080M安装驱动

20230311给Ubuntu18.04下的GTX1080M安装驱动 2023/3/11 12:50 2. 安装GTX1080驱动 安装 Nvidia 驱动 367.27 sudo add-apt-repository ppa:graphics-drivers/ppa 第一次运行出现如下的警告&#xff1a; Fresh drivers from upstream, currently shipping Nvidia. ## Curren…

C++语法规则4(C++面向对象)

接口&#xff08;抽象类&#xff09; 接口描述了类的行为和功能&#xff0c;而不需要完成类的特定实现。C 接口是使用抽象类来实现的&#xff0c;抽象类与数据抽象互不混淆&#xff0c;数据抽象是一个把实现细节与相关的数据分离开的概念。 如果类中至少有一个函数被声明为纯虚…

在Win 11下使用Visual Studio 2019和cygwin编译JBR(Java SDK 17)源码

很多文章介绍了JDK 8和JDK11源码在Linux编译&#xff0c;很少有人介绍了JDK 17在windows的编译过程&#xff0c;所以写了这篇文章&#xff0c;为什么选用JBR 17版本&#xff0c;因为JBR17 版本集成了HotSwapAgent功能&#xff0c;具体HotSwapAgent有什么用&#xff0c;请看我前…

[N1CTF 2018]eating_cms1

一个cms&#xff0c;先打开环境试了一下弱口令&#xff0c;无效&#xff0c;再试一下万能密码&#xff0c;告诉我有waf&#xff0c;先不想怎么绕过&#xff0c;直接开扫&#xff08;信息收集&#xff09;访问register.php注册一个账号进行登录上面的链接尝试用php读文件http://…

学习笔记:基于SpringBoot的牛客网社区项目实现(三)之MyBatis入门

一、数据库建表 二、entity目录下创建user实体类 三、dao目录下创建userMapper映射接口 Mapper public interface UserMapper {User selectById(int id);User selectByName(String username);User selectByEmail(String email);int insertUser(User user);int updateStatus(i…