19 Shell编程之条件语句
目录
19.1 条件测试操作
19.1.1 文件测试
19.1.1 整数值比较
19.1.3 字符串比较
19.1.4 逻辑测试
19.2 if条件语句
19.2.1 if语句的结构
19.2.2 if语句应用示例
19.3 case分支语句
19.3.1 case语句的结构
19.3.2 case语句应用示例
19.1 条件测试操作
Shell环境根据命令执行后的返回状态值($?)来判断是否执行成功,当返回值为0时表示成功,否则(非0值)表示失败或异常。使用专门的测试工具——test命令,可以对特定条件进行测试,并根据返回值来判断条件是否成立(返回值为0表示条件成立)。
使用test测试命令时,包括以下两种形式。
test 条件表达式
[ 条件表达式 ] //需要注意中括号前后必须加空格
这两种方式的作用完全相同,但通常一种形式更为常用,也更贴近编程习惯。需要注意的是,方括号“[ ”或“]”与条件表达式之间需要至少一个空格进行分隔。
根据需要测试的条件类别不同,条件表达式也不同。比较常用的条件操作包括文件测试、整数值比较、字符串比较、以及针对多个条件的逻辑测试。
19.1.1 文件测试
文件测试指的是根据特定的路径名称,判断对应的是文件还是目录,或者判断文件是否可读、可写、可执行等。文件测试的常见操作选项如下,使用时将测试对象放在操作选项之后即可。
类型 | 作用 |
-d | 测试是否为目录(Directory)。 |
-e | 测试目录或文件是否存在(Exist)。 |
-f | 测试是否为文件(File)。 |
-r | 测试当前用户是否有权限读取(Read)。 |
-w | 测试当前用户是否有权限写入(Write)。 |
-x | 测试是否设置有可执行(Excute)权限。 |
执行条件测试操作以后,通过预定义变量$?可以获得测试命令的返回状态值,从而判断该条件是否成立。
若测试条件不成立,则测试操作的返回值将不为0(通常为1)。
通过查看变量$?的值可以判断前一步的条件测试结果,但是操作比较繁琐,输出结果也并不是很直观。为了更直观地查看测试结果,可以结合命令分隔符“&&”和echo命令一起使用,当条件成立时直接输出“YES”。其中,“&&”符号表示“而且”关系,只有当前面的命令执行成功后才会执行后面的命令,否则后面的命令将会被忽略。
19.1.1 整数值比较
整数值比较指的是根据给定的两个整数值,判断第一个数与第二个数的关系,如是否大于、等于、小于第二个数。整数值比较的常用操作选项如下,使用时将操作选项放在要比较的两个整数之间。
类型 | 作用 |
-eq | 第一数等于(Equal)第二个数。 |
-ne | 第一个数不等于(Not Equal)第二个数。 |
-gt | 第一个数大于(Greater Than)第二个数。 |
-lt | 第一个数小于(Lesser Than)第二个数。 |
-le | 第一个数小于或等于(Lesser or Equal)第二个数。 |
-ge | 第一个数大于或等于(Greater or Equal)第二个数。 |
整数值比较在Shell脚本编写中的应用较多。例如,用来判断已登录用户数量、开启进程数、磁盘使用率是否超标,以及软件版本号是否符合要求等。实际使用时,往往会通过变量引用、命令替换等方式来获取一个数值。
例如,若要判断当前已登录的用户数,当超过五个时输出“Too many”,可以执行以下操作。
又如,若要判断物理内存(Mem)当前的磁盘缓存大小,当低于1024MB时输出具体数值,可以执行以下操作。其中,“free -m”命令表示以MB为单位输出内存信息,提取的空闲内存数值通过命令替换赋值给变量FreeCC。
19.1.3 字符串比较
字符串比较通常用来检查用户输入、系统环境等是否满足条件,在提供交互式操作的Shell脚本中,也可以用来判断用户输入的位置参数是否符合要求。字符串比较的常用操作选项如下。
类型 | 作用 |
= | 第一个字符串与第二个字符串相同。 |
!= | 第一个字符串与第二个字符串不相同,其中“!”符号表示取反。 |
-z | 检查字符串是否为空(zone),对于未定义或赋予空值的变量将视为空串。 |
例如,若要判断当前系统的语言环境,当发现不是“en.US” 时输出提示信息“Not en.US”,可以执行以下操作:
又如,在Shell脚本应用中,经常需要用户输入 “yes”或“no”来确认某个任务。以下操作展示了确认交互的简单过程,实际使用时还会根据变量“ACK”的取值分别执行进一步的操作。
19.1.4 逻辑测试
逻辑测试指的是判断两个或多个条件之间的依赖关系。当系统任务取决于多个不同的条件时,根据这些条件是否同时成立或者只要有其中一个成立等情况,需要有一个测试的过程。常用的逻辑测试操作如下,使用时放在不同的测试语句或命令之间。
类型 | 作用 |
&& | 逻辑与,表示“而且”,只有当前后两个条件都成立时,整个测试命令的返回值才为0(结果成立)。使用test命令测试时,“&&”可改为“-a”。 |
|| | 逻辑或,表示“或者”,只要前后两个条件中有一个成立,整个测试命令的返回值即为0(结果成立)。使用test命令测试时,“||”可改为“-o”。 |
! | 逻辑否,表示“不”,只有当指定的条件不成立时,整个测试命令的返回值才为0(结果成立)。 |
在上述逻辑测试的操作选项中,“&&”和“||”通常也用于间隔不同的命令操作,起作用时相似的。实际上此前已经接触“&&”操作应用,如“make && make install”的编译安装操作。
例如要判断当前Linux系统的版本内核本是否大于3.4,可以执行以下操作。其中,内核版本号通过uname和awk命令获得。
19.2 if条件语句
实际上使用“&&”和“||”逻辑测试已经可以完成简单的判断并执行相应的操作,但是当需要选择执行的命令语句较多时,这种方式将使执行代码显得很复杂,而使用专门的if条件语句,可以更好地整理脚本结构,使得层次分明,清晰易懂。
19.2.1 if语句的结构
在Shell脚本应用中,if语句是最为常见的一种流程控制方式,用来根据特定的条件测试结果,分别执行不同的操作(如果......那么......)。根据不同的复杂程度,if语句的选择结构可以分为三种基本类型,适用于不同的应用场合。
1.单分支if语句
if语句的“分支”指的是不同测试结果对应的执行语句(一条或多条),对于单分支的选择结构,只有在“条件成立”时才会执行相应的代码,否则不执行任何操作。单分支if语句的语法格式如下所示:
在上述语句结构中,条件测试操作既可以是“[条件表达式]”语句,也可以时其它可执行的命令语句;命令序列指的是一条或多条可执行的命令行,也包括嵌套使用的if语句或其他流程控制语句。
单分支if语句的执行流程:首先判断条件测试操作的结果,如果返回值为0,表示条件成立,执行then后面的命令序列,一直到遇见fi结束判断为止,继续执行其他脚本代码;如果返回值不为0,则忽略then后面的命令序列,直接跳至fi行一役后执行其它脚本代码。
2.双分支if语句
对于双分支的选择结构,要求针对“条件成立”“条件不成立”两种情况分别执行不同的操作。双分支if语句夫人语法格式如下:
双分支if语句的执行流程:首先判断条件测试操作的结构,如果条件成立,则执行then后面的命令序列1,忽略else及后面的命令序列2,知道遇见fi结束判断;如果条件不成立,则忽略then及后面的命令序列1,直接跳至else后面的命令序列2并执行,知道遇见fi结束判断。
3.多分支if语句
由于if语句可以根据测试结构的成立、不成立分别执行操作,所以能够嵌套使用,进行多次判断。多分支if语句的语法格式如下。
多分支if语句的执行流程:首先判断条件测试1的结构,如果条件1成立,则执行命令序列1,然后跳至fi结束判断;如果条件1不成立,则继续判断条件测试操作2的结构,如果条件2成立,则执行命令序列2,然后跳至fi结束判断......如果虽有的条件都不满足,则执行else后面的命令序列n,直接遇见fi结束判断。
19.2.2 if语句应用示例
1.单分支if语句应用
很多 Linux 用户习惯上将光盘设备挂载到/media/cdrom 目录下,但 CentOS7 系统默认并没有建立此目录。若需要在 Shel 脚本中执行挂载光盘的操作,建议先判断挂载点目录是否存在,若不存在则新建此目录。
例如,有些特权命令操作要求以root用户执行,如果当前用户不是root,那么再执行这些命令就没有必要(肯定会失败)。针对这种情况,在脚本中可以先判断当前用户是不是root,如果不是则报错并执行"exit 1"命令退出脚本(1 表示退出后的返回状态值),而不再执行其他代码。
当普通用户执行 chkifroot.sh 脚本时,由于"非root 用户”的条件成立,因此会提示权限
不足并退出脚本(使用“exit 1"退出脚本后,fi之后的 fdisk 命令将不会执行)。
当 root 用户执行 chkifroot.sh 脚本时,由于“非 root 用户”的条件不成立,所以if 语句不
执行任何操作,正常执行fi之后的脚本代码。
2.双分支if语句应用
双分支if语句只是在单分支的基础上针对“条件不成立"的情况执行另一种操作,而不是“坐视不管"地不执行任何操作。例如,若要编写一个连通性测试脚本 pinghost.sh,通过位置参数$1提供目标主机地址,然后根据 ping 检测结果给出相应的提示,可以参考以下操作过程。
在上述脚本代码中,为了提高 ping 命令的测试效率,使用了"-c""-i""-W选项,分别指定
只发送三个测试包、间隔 0.2 秒、超时 3秒。另外,通过“&>/dev/nul"屏蔽了 ping 命令执行
过程的输出信息。执行 pinghost.sh 脚本的效果如下所示。
例如,通过 Shel 脚本检査 vsftpd 服务是否运行,如果已经运行则列出其监听地址、PID 号,否则输出提示“警告:vsftpd 服务不可用!”。其中,pgrep 命令的“-x"选项表示查找时使用精确匹配。
执行chkvsftpd.sh脚本的效果如下所示。
3.多分支if语句应用
与单分支、双分支if语句相比,多分支if语句的结构能够根据多个互斥的条件分别执行不同的操作,实际上等同于嵌套使用的i语句。例如,若要编写一个成绩分档的脚本gradediv.sh,根据输入的考试分数不同来区分优秀、合格、不合格三挡,可以参考以下操作过程。
执行gradediv.sh脚本的效果如下所示。
19.3 case分支语句
case 语句可以使脚本程序的结构更加清晰、层次分明,本节就来学习 case 语句的语法结构及应用。
19.3.1 case语句的结构
case语句主要适用于以下情况:某个变量存在多种取值,需要对其中的每一种取值分别执行不同的命令序列。这种情况与多分支的if语句非常相似,只不过if语句需要判断多个不同的条件,而 case 语句只是判断一个变量的不同取值。
case分支语句的语法结构如下所示。
在上述语句结构中,关键字 case 后面跟的是"变量值”,[即“$变量名”。整个分支结构包括在 case...esac 之间,中间的模式 1、模式 2、……、*对应为变量的不同取值(程序期望的取值),其中*作为通配符,可匹配任意值。
case 语句的执行流程:首先使用“变量值"与模式1进行比较,若取值相同则执行模式1后的命令序列,直到遇见双分号"…"后跳转至 esac,表示结束分支;若与模式1不相匹配,则继续与模式2进行比较,若取值相同则执行模式2后的命令序列,直到遇见双分号"…;”后跳转至 esac,表示结束分支…依此类推,若找不到任何匹配的值,则执行默认模式“*)后的命令序列,直到遇见 esac 后结束分支。
使用 case 分支语句时,有几个值得注意的特点如下所述。
1.case 行尾必须为单词“in”,每一模式必须以右括号")”结束。
2.双分号";;"表示命令序列的结束。
3.模式字符串中,可以用方括号表示一个连续的范围,如“[0-9]”;还可以用竖杠符号“||”表示或,如“A|B”。
4.最后的“*)”表示默认模式,其中的*相当于通配符。
19.3.2 case语句应用示例
1.检查 用户输入的字符类型
提示用户从键盘输入一个字符,通过 case 语句判断该字符是否为字母、数字或者其他控制字符,并给出相应的提示信息。
测试并确认hitkey.sh脚本的执行结果如下所示。
2.编写系统服务脚本
编写一个名为 myprog 的系统服务脚本,通过位置变量$1 指定的 start、stop、restart、status 控制参数,分别用来启动、停止、重启 sleep 进程,以及査看 sleep 进程的状态。其中,命令 sleep 用来暂停指定秒数的时间,这里仅用做测试,在实际运维工作中应将 sleep改为相应后台服务的控制命令序列。
测试并确认mygrog脚本的执行结果如下所示。
在 Linux 系统中,源码软件包编译安装后提供的服务控制脚本使用了 case 分支语句;也有一些源码包没有提供服务控制脚本,编译安装后可参照上例自行编写服务控制脚本。平时控制各种系统服务时,提供的 start、stop、restart 等位置参数,正是由 case 语句结构来识别并完成相应操作的。有兴趣的同学可自行查阅这些脚本内容。若要将 myprog 服务交给 systemd 来管理,还需要在/lib/systemd/system 目录下添加相应的 myprog.service 配置文件。
相关文章:

19 Shell编程之条件语句
目录 19.1 条件测试操作 19.1.1 文件测试 19.1.1 整数值比较 19.1.3 字符串比较 19.1.4 逻辑测试 19.2 if条件语句 19.2.1 if语句的结构 19.2.2 if语句应用示例 19.3 case分支语句 19.3.1 case语句的结构 19.3.2 case语句应用示例 19.1 条件测试操作 Shell环境根据命令执行后…...

生产看板管理系统内容有哪些?
相信很多做生产管理的朋友都会遇到如下问题,我就在想,是否能一个创建“透明的”的工作场所?让员工和管理者能够实时查询生产进度,及时发现生产中的问题。 生产进度难追踪 生产过程不透明 生产决策缺乏数据支持 ——能…...

玩转数据库索引
1、概述 通常我们要对数据库进行优化,主要可以通过以下五种方法。 计算机硬件调优应用程序调优数据库索引优化SQL语句优化事务处理调优 本篇文章将向大家介绍数据库中索引类型和使用场合,本文以SQL Server为例,对于其他技术平台的朋友也是有…...

公共云遣返的经济性
在过去的几年里,显而易见的是,尽管公有云具有所有优势,但它并不能大规模地节省成本。它在一定程度上提高了生产力,但不会降低您的成本。公有云的好处在于,它提供了一个非常强大的价值主张,即基础设施可以立…...

夏季河湖防溺水新举措:EasyCVR+AI视频智能监控系统保障水域安全
近日一则新闻引起大众关注,有网友发布视频称,假期在逛西湖时,发现水面上“平躺”漂浮着一名游客在等待救援。在事发3分钟内,沿湖救生员成功将落水游客救到了岸边。 随着夏季的到来,雨水增多,各危险水域水位…...
2024年最新【交安】公路水运安全员备考题库。
46.( )负责建筑施工企业安全生产许可证的颁发和管理,并接受国务院建设主管部门的指导和监督。 A.国务院建设主管部门 B.国务院安全生产监督管理部门 C.省、自治区、直辖市人民政府建设主管部门 D.省、自治区、直辖市人民政府安全生产监督管理部门 答案&…...

Excel 宏录制与VBA编程 —— 16、InputBox函数的使用方式
Input函数基本操作 InputBox函数的Type参数使用技巧(输入类型限制,若输入类型不符系统提示) 关注 笔者 - jxd...

【ai】tx2 nx : yolov4加入initLibNvInferPlugins构建
先说结果:make 成功 插件头文件 复制一份: /** Copyright 1993-2021 NVIDIA Corporation. All rights reserved.** NOTICE TO LICENSEE:** This source code and/or documentation ("Licensed Deliverables") are* subject to NVIDIA intellectual property right…...

【Proteus仿真】【Arduino单片机】基于物联网新能源电动车检测系统设计
文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器,使用LCD1602液晶显示模块、WIFI模块、蜂鸣器、LED按键、ADC、DS18B20温度传感器等。 主要功能: 系统运行后,LCD1602显示温…...

MobaXterm破解专业版方法
MobaXterm专业版(含授权)-CSDN博客 1.安装python3环境,使用vscode打开文件夹,新建终端,在终端中执行命令 python MobaXterm-Keygen.py "DoubleSine" 20.2 (20.2为MobaXterm版本号,…...

0基础学JMeter:如何开始简单的WEB压力测试(一)
背景 最近工作上被安排针对Web网站进行性能压测,以评估特定的硬件配置下Web网站可支持的并发用户数。考虑到JMeter是流行的Web性能压测工具,因此趁着这次机会上网查阅了很多关于JMeter的资料,也自己动手进行软件的配置和调测,从最…...
ArcGIS数据处理与制图
在数字化和智能化的浪潮中,GIS(地理信息系统)和GPT(生成式预训练模型)的结合正日益成为推动科研、城市规划、环境监测等领域发展的关键技术。GIS以其强大的空间数据处理、先进的空间分析工具、灵活的地图制作与可视化能…...

基于Java微信小程序校园订餐系统设计和实现(源码+LW+调试文档+讲解等)
💗博主介绍:✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者,博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗 🌟文末获取源码数据库🌟感兴趣的可以先收藏起来,还…...
基于文件的本地数据库组件 DuckDB, ChDB, SQLite, LevelDB, RocksDB
OLTP 与 OLAP 的区别: OLTP(on-line transaction processing) 联机事务处理,主要就是一些传统的数据库,比如 Mysql。OLAP(On-Line Analytical Processing) 联机分析处理,主要应用在大数据分析处理领域,比如 Clickhous…...
日志记录功能
需求描述: 1,可记录页面操作模块、按钮的日志记录 2,记录详细的指定操作数据日志 3,记录的数据可能需要查询表 4,需要考虑到扩展性及个性化定制 表结构设计: CREATE TABLE YES_DEV.T_COMM_OPERATION_LOG (ID BINARY_BIGINT NOT NULL,OPERATOR VARCHAR(128),OPERATION_MO…...
Android中的多线程与线程池详解
Android中的多线程与线程池详解 一、技术难点 在Android开发中,多线程和线程池是处理复杂任务、提高应用性能和响应性的关键技术。然而,这些技术也带来了一些技术难点。 1. 多线程技术难点 线程同步:多线程环境下,数据访问的同…...

使用LangChain+Ollama自己做的一个和大语言模型聊天的网站支持上下文对话,学习记录。
0.引言 在自己学习的过程中可以自己做一个和聊天大模型对话的一个小网站,成就感不亚于人生第一次跑完10km。 1.项目介绍 前端代码:Vue3, MarkDownIT. 后端代码:Python3, Fernet库, OpenAPI, LangChain, Ollama. Ollama 本地模型的部署和管理…...

excel数据透视
Excel中,数据透视图(PivotChart)和数据透视表(PivotTable)是两个紧密相关的工具,用于分析数据。数据透视表是数据透视图的数据源,也就是说,数据透视图是基于数据透视表中的数据创建的…...

七、(正点原子)Linux并发与竞争
Linux是多任务操作系统,肯定会存在多个任务共同操作同一段内存或者设备的情况,多个任务甚至中断都能访问的资源叫做共享资源。在驱动开发中要注意对共享资源的保护,也就是要处理对共享资源的并发访问。 一、并发与竞争 1、简介 并发就是多个…...
vue2+TS,el-table表格单选的写法
1.打开表格 //父组件引入 <customerChoose ref"customerChooseRef" onSure"setOrderInfoFn"></customerChoose>//子传父,接收值,操作private async setOrderInfoFn(data) {this.form.customerId data.idthis.form.cu…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...

ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...

Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...

论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving
地址:LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂,正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...

java高级——高阶函数、如何定义一个函数式接口类似stream流的filter
java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用(Math::max) 2 函数接口…...