第二十四章 流程控制_ if分支

第二十四章 流程控制: if分支和输入

正如许多编程语言一样Shell也有自己的条件分支语句。有时需要根据情况进行相应的处理,因此可以通过条件分支语句实现,本章主要介绍的是if分支语句。

if语句

在Shell中if语句语法格式如下:

if commands; thencommands
[elif commmands; thencommands...]
[elsecommands]
fi

其中commands是命令列表。


例如根据变量x是否为5输出其结果信息:

x=5if [ "$x" -eq 5 ]; thenecho "x equals 5."
elseecho "x does not equal 5."
fi

执行结果如下图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

本例中,将变量设置为5,通过if语句进行判断,结果为真,因此输出’x equals 5.‘’。

使用test

Shell不像其他编程语言直接使用条件表达式进行条件判定,在Shell中使用test进行各种检查比较。该命令有两种形式。第一种:


test expression



第二种,也是更流向的形式:

[ expression ]


其中,expression是一个表达式,求值结果要么为真,要么为假。如果为test返回推出状态值0;如果为假,则返回1。

test和[其实都是命令。在bash中,两者均为内建命令,但也作为独立的可执行文件存在与/usr/bin中,供其它Shell使用。表达式其实就是[命令的参数,该命令同时要求将]作为其最后一个参数。

文件表达式

test文件表达式

表达式什么情况下为真
file1 -ef file2file1和file2都具有相同的i节点编号(两个文件名通过硬链接指向同一个文件)
file1 -nt file2file1比file2新
file1 -ot file2file1比file2旧
-b filefile存在且为块设备文件
-c filefile存在且为字符设备文件
-d filefile存在且为目录
-e filefile存在
-f filefile存在且为普通文件
-g filefile存在且设置了SGID位
-G filefile存在且为有效组ID所有
-k filefile存在且设置了"粘滞位"
-L filefile存在且为符号链接
-O filefile存在且为有效用户ID所有
-p filefile存在且为具名管道
-r filefile存在且可读
-s filefile存在且不为空
-S filefile存在且为网络套接字
-t fdfd是与终端关联的文件描述符。该表达式可用于判断标准输入/输出/错误是否被重定向
-u file文件存在且设置SUID位
-w filefile存在且可写(有效用户具有写权限)
-x filefile存在且可执行(有效用户具有执行/搜索权限)

例如:判读文件~/.bashrc的文件类型及其文件状态

代码如下:


#!/bin/bash# test-file:评估文件的状态FILE=~/.bashrcif [ -e FILE ]; then#判断文件类型if [ -f FILE ]; thenecho "$FILE is a regular file."elif [ -d FILE ]; thenecho "$FILE is a directory"elif [ -b FILE ]; thenehco "$FILE is a block device file"elif [ -c FILE ]; thenecho "$FILE is a character device file"elif [ -L FILE ]; thenecho "$FILE is a symbol link file"elif [ -S FILE ]; thenecho "$FILE is a socket file"elif [ -p FILE ]; thenecho "$FILE is a pipe file"fiif [ -r FILE ]; thenecho "$FILE is readable."fiif [ -w FILE ]; thenecho "$FILE is writable."fiif [ -x FILE ]; thenecho "$FILE is executable/searchable"fielseecho "$FILE does not exist"exit 1
fi	exit

运行结果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


字符串表达式

test的字符串表达式

表达式什么情况下为真
stringstring不为空
-n stringstring的长度大于0
-z stringstring的长度等于0
string1 == string2string1和string2相同。也可以使用单等号,但最好使用双等号其不符号POSIX标准
string1 != string2string1和string2不相同
string1 > string2string1的排序位于string2之后
string1 < string2string1的排序位于string2之前


在使用test时,必须将表达式操作符>和<引用起来(或者通过反斜线转义)。如果不这么做,两者会被Shell解释为重定向操作符,有可能会造成破坏性后果。另外还要注意,尽管Bash文档中说过排序遵从当前语言环境的排序规则,但事实并非如此。一直到4.0版本,Bash一直使用的是ASCII(POSIX)排序。这个问题在4.1版本中才纠正过来。



例如:计算字符串的值

代码如下:

#!/bin/bash#test-string:计算字符串值ANSWER=maybeif [ -z "$ANSWER" ]; thenecho "There is no answer." >&2exit 1
fiif [ "$ANSWER" = "yes" ]; thenecho "The answer is YES."
elif [ "$ANSWER" = "no" ]; thenecho "The answer is NO."
elif [ "$ANSWER" = "maybe" ]; thenecho "The answer is MAYBE."
elseecho "The answer is UNKNOWN."
fi

该程序运行结果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


整数表达式

test的整数表达式

表达式什么情况下为真
integer1 eq interger2integer1等于interger2
integer1 ne interger2integer1不等于integer2
integer1 -le integer2integer1小于或等于integer2
integer1 -lt integer2integer1小于integer2
integer1 -ge integer2integer1大于或等于integer2
integer1 -gt integer2integer1大于integer2

例如:计算整数的值

代码如下:

#!/bin/bash#test-integer: 计算整数值INT=-5if [ -z "$INT" ]; thenecho "INT is empty." >&2exit 1
fiif [ "$INT" -eq 0 ]; thenecho "INT is zero."elseif [ "$INT" -lt 0 ]; thenecho "INT is negative."elseecho "INT is positive."fiif [ $((INT % 2)) -eq 0 ]; thenecho "INT is even."elseecho "INT is odd."fi
fi

运行结果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

更现代的test

Bash的现代版本包含了一个可以作为test增强版的复合命令,其用法如下:


[[ expression ]]



和test一样,其中的expression是一个表达式,结果要么为真,要么为假。[[]]命令(支持所以test表达式)类似于test另外还加入一个重要的全新的字符串表达式。

string1 =~ regex



如果string1匹配ERE regex,则返回为真。例如在整数表达式的例子中,如果常量INT含有整数以为的其它值,脚本就会执行失败。脚本需要一种方法来核实该常量包含的是整数,可以使用[[]]配合=~字符传表达式,按照下列方式改进脚本:
#!/bin/bash#test-integer2: 计算整数值INT=-5if [[ "$INT" =~ ^-?[0-9]+$ ]]; thenif [ "$INT" -eq 0 ]; thenecho "INT is zero."elseif [ "$INT" -le 0 ]; thenecho "INT is negative."elseecho "INT is positive."fiif [ $((INT % 2)) -eq 0 ]; thenecho "INT is even."elseecho "INT is odd."fifi
elseecho "INT is not an integer." >&2exit 1
fi

运行结果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


从运行结果来看和之前的例子运行结果相同,通过正则表达式可以判断是否为数字。将INT的值限制为只能是以可选的减号起始,后跟一个或多个数字的字符串,同时也消除了INT为空值的可能。

[[]]的另一个特征是其中的==操作符支持和路径扩展一样的模式匹配。


(())-为整数设计

除了复合命令[[]],bash还支持另一种复合命令(()),它在整数操作时用得上。该命令支持所有的算术求值。

(())可用于执行算术真值测试( arithmetic truth test)。如果算术求值的结果不为0,则测试结果为真。

有了(()),可以简化一下test-integer2的副本:

#!/bin/bash#test-integer2:计算整数的值INT=-5if [ "$INT" =~ ^-?[0-9]+$ ]; thenif ((INT == 0)); thenecho "INT is zero."elseif ((INT < 0)); thenecho "INT is negative."elseecho "INT is positive."fiif (( ((INT % 2)) == 0 )); thenecho "INT is even."elseecho "INT is odd."fielseecho "INT is not an integer." >&2exit 1
fi

(())复合命令是Shell语法的一部分,而非普通命令,并且只能处理整数,因此它能够通过名称来识别变量,不需要执行扩展操作。


组合表达式

将多个表达式组合在一起,形成更为复杂的测试。表达式通过逻辑操作符组合起来。test和[[]]可用的逻辑操作有3种,分别是AND、OR、NOT。test和[[]]使用不同的操作符来表示这些逻辑操作。

逻辑操作符

操作test[[]]和(())
AND-a&&
OR-o||
NOT!!

例如:判断整数是否位于特定取值区间内

代码如下:

#!/bin/bash#test-integer3:确定整数是否位于特定取值区间内MIN_VAL=1
MAX_VAL=100INT=50if [[ "$INT" =~ ^-?[0-9]+$ ]]; thenif [[ "$INT" -ge "$MIN_VAL"  && "$INT" -le "$MAX_VAL" ]]; thenecho "$INT is within $MIN_VAL to $MAX_VAL."elseecho "$INT is out of range."fi
elseecho "INT is not an integer." >&2exit 1
fi

运行结果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在该脚本中通过[[]]实现,该操作符包含由&&分隔的两个表达式。可以使用test改写:


if [ "$INT" -ge "$MIN_VAL" -a "$INT" -le "$MAX_VAL" ]; thenecho "$INT is within $MIN_VAL to $MAX_VAL."
elseecho "$INT is out of range"
fi

否定操作符!会表达式的结果求反。例如要找出指定取值区间之外的INT值:

#!/bin/bash#test-interger4:确定整数是否位于指定取值区间之外MAX_VAL=100
MIN_VAL=1INT=50if [[ "$INT" =~ ^-?[0-9]+$ ]]; thenif [[ ! ("$INT" -ge "$MIN_VAL" && "$INT" -le "$MAX_VAL") ]]; thenecho "$INT is outside $MIN_VAL to $MAX_VAL."elseecho "$INT is in range."fielseecho "INT is not an integer." >&2exit 1
fi

运行结果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在表达式两边加上括号,用于分组。如果不见,!仅用于第一个表达式,而非两个表达式的组合。使用test的代码如下:

if [ ! \( "$INT" -ge "$MIN_VAL" -a "$INT" -le "$MAX_VAL"\)]; thenecho "$INT is outside $MIN_VAL to $MAX_VAL."
elseecho "$INT is in range."
fi

test和[[]]的功能基本差不多,test是长期存在的标准(也是标准Shell的POSIX规范的一部分,多用于系统启动脚本),而[[]]是Bash(包括其它少数现代Shell)专用的。

控制操作符:另一种分支方式

Bash提供了两种可以执行分支的操作符,即&&(AND)和||(OR)操作符,它们类似于[[]]复合命令中的逻辑操作符。&&的语法如下:


command1 && command2


|| 的语法如下:


command1 || command2


对于&&的操作符,先执行command1,仅当command1执行成功时才执行command2。对于||操作符,先执行command1,仅当command1执行失败时才执行command2。

例如:先创建目录,然后执行cdmingl

mkdir temp && cd temp

该命令会创建一个temp的目录,如果创建成功,就将当前的工作目录更改为temp。第二个命令仅在mkdir命令执行成功的情况下执行。

测试目录temp的存在,当不存在时创建temp目录:

[[ -d temp ]] || mkdir temp

这种结构便于在脚本中处理错误。

read-从标准输入读取值


内建的read命令可以从标准输入读取一行。用法如下:


read [-options] [variable…]



其中options是选项,variable是一个或多个变量,用于保存输入值。如果未指定变量,则输入值保存在Shell变量REPLY中。

例如:对输入的数值进行计算

代码如下:

#!/bin/bash#test-integer4:计算整数的值echo -n "Please enter an integer ->"
read numif [[ "$num" =~ ^-?[0-9]+$ ]]; thenif [ "$num" -eq 0 ]; thenecho "$num is zero."fiif [ "$num" -lt 0 ]; thenecho "$num is negative."elseecho "$num is positive."fiif [ (( num % 2)) -eq 0 ]; thenecho "$num is even."elseecho "$num is odd."fielseecho "$int is not an integer." >&2exit 1
fi

输出结果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


read选项

选项描述
-a array将输入分配给数组(从索引0开始)。
-d delimiter将字符串delimiter中的第一个字符(而非换行符)作为输入结束
-c使用Readline处理输入。这允许使用和命令行相同的方式编辑输入
-i string如果用户直接按Enter键,使用string作为默认值。需要配合-e选项使用
-n num从输入中读取num个字符,而非读取一行
-p prompt将字符串prompt作为输入提示来显示
-r原始模式(raw mode)。不将反斜线解释为转义
-s静默模式。在用户输入字符时不回显。该模式适用于输入密码或其它机密信息
-t seconds超时。seconds秒之后终止输入。如果输入超时,read返回非0退出状态值
-u fd从文件描述符fd(而非标准输入)中读取输入

例如:读取“机密”输入:

代码如下:

#!/bin/bash#read-secret:输入"机密"if read -t 10 -sp "Enter secret passprase >" sectet_pass; thenecho -e "\nSecret passphrase = '$secret_pass' "
elseecho -e "\nInput timed out" >&2exit 1
fi

程序运行结果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


IFS

Shell通常会对提供给read的输入进行单词分割。Shell变量内部字段分割符(Internal Field Separator , IFS)控制着此行为。IFS的默认值包含了空格符、制表符、换行符,它们到可用于分隔单词。

例如:从文件读取字段

#!/bin/bash#read-ifs: 从文件中读取字段FILE=/etc/passwdread -p "Enter a username > "  user_namefile_info="$(grep "^$user_name:" $FILE)" #查找包含user_name的值的所在行内容if [ -n "$file_info" ]; thenIFS=":" read user pw uid gid name home shell <<< "$file_info"echo "User=     '$user'"echo "UID=      '$uid'"echo "GID=      '$gid'"echo "Full Name = '$name'"echo "Home Dir. = '$home'"echo "Shell = '$shell'"
elseecho "No such user '$user_name'" >&2exit 1
fi

运行结果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意:read命令不能放入管道也就是说下面这种用法是禁止的:


echo “foo” | read


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

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

相关文章

电脑网络重置,找不到原先自家的WIFI,手机还能正常连接并上网

问题排查&#xff1a;1、电脑感觉网络太慢&#xff0c;因此打算点击了网络重置 2、点击提示会删除网络&#xff0c;在五分钟后关机重启 3、从设备管理器设备的无线wifi属性-事件中发现删除记录 4、选择更新驱动程序 5、从列表中选取 6、更改回老驱动版本 备选方案&#…

C语言_预处理详解

1. 预定义符号 C语言设置了一些预定义符号&#xff0c;可以直接使用&#xff0c;预定义符号也是在预处理期间处理的 1 __FILE__ //进行编译的源文件 2 __LINE__//文件当前的行号 3 __DATE__ //文件被编译的日期 4 __TIME__//文件被编译的时间 5 __STDC__//如果编译器遵循ANSI…

【QT】使用QT帮助手册找控件样式

选择帮助—》输入stylesheet(小写)—》选择stylesheet—》右侧选择Qt Style Sheets Reference 2.使用CtrlF—》输入要搜索的控件—》点击Customizing QScrollBar 3.显示参考样式表–》即可放入QT-designer的样式表中

SQL知识合集(二):函数篇

TRIM函数 作用&#xff1a;去掉字符串前后的空格 SELECT * FROM your_table_name WHERE TRIM(column_name) ; COALESCE函数 作用&#xff1a;返回其参数中的第一个非 NULL 值。它可以接受多个参数&#xff0c;并从左到右依次评估这些参数&#xff0c;直到找到第一个非 NUL…

Cursor 工具项目构建指南: Uniapp Miniprogram 环境下的 Prompt Rules 约束

简简单单 Online zuozuo: 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo :本心、输入输出、结果 简简单单 Online zuozuo : 文章目录 Cursor 工具项目构建指南: Uniapp Miniprogram 环境下的 Prompt Rules 约束前言项目简…

Java转Go日记(六十):gin其他常用知识

1. 日志文件 package mainimport ("io""os""github.com/gin-gonic/gin" )func main() {gin.DisableConsoleColor()// Logging to a file.f, _ : os.Create("gin.log")gin.DefaultWriter io.MultiWriter(f)// 如果需要同时将日志写入…

cocos单例工厂和自动装配

cocos单例工厂和自动装配 1 单例工厂 1.1 分析 实例字典 原理很简单&#xff0c;只是一个map&#xff0c;确保每个类只保留一个实例&#xff1b; private static _instances new Map<string, any>();获取与存储实例 这边使用的方式是生成一个唯一的id存储在类上&…

django paramiko 跳转登录

在使用Django框架结合Paramiko进行SSH远程操作时&#xff0c;通常涉及到自动化脚本的执行&#xff0c;比如远程服务器上的命令执行、文件传输等。如果你的需求是“跳转登录”&#xff0c;即在登录远程服务器后&#xff0c;再通过该服务器的SSH连接跳转到另一台服务器&#xff0…

《C++初阶之类和对象》【命名空间 + 输入输出 + 缺省参数 + 函数重载】

【命名空间 输入&输出 缺省参数 函数重载】目录 前言&#xff1a;---------------hello world---------------比较C语言和C的第一个程序&#xff1a;hello word ---------------命名空间---------------什么是命名空间&#xff1f;怎么使用命名空间&#xff1f;怎么定义…

[USACO1.5] 八皇后 Checker Challenge Java

import java.util.*;public class Main {// 标记 对角线1&#xff0c;对角线2&#xff0c;所在x轴 是否存在棋子static boolean[] d1 new boolean[100], d2 new boolean[100], d new boolean[100]; static int n, ans 0;static int[] arr new int[14]; // 记录一轮棋子位置…

云服务器Xshell登录拒绝访问排查

根据你的描述&#xff0c;使用Xshell 8登录云服务器时显示“拒绝访问”&#xff0c;可能涉及多个原因。以下结合搜索结果整理出排查和解决方法&#xff0c;按优先级排序&#xff1a; 一、检查基础网络与端口连通性 本地网络与服务器IP是否可达 在本地电脑的CMD中执行 ping 服务…

Python爬虫实战:研究urlunparse函数相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上的数据量呈现出指数级增长。如何从海量的网页数据中高效地获取有价值的信息,成为了学术界和工业界共同关注的问题。网络爬虫作为一种自动获取网页内容的技术,能够按照预定的规则遍历互联网上的网页,并提取出所需…

Spring AI学习一

随着Chatpt的火爆&#xff0c;现在Spring官方也开始支持AI了并推出了Spring AI框架&#xff0c;目前还没发布正式版本&#xff0c;这里可以先看一下官方依赖的版本。 Spring官网地址可以看这里&#xff1a;Spring | Home 目前官网上是有这两个版本&#xff1a;1.0.0和1.1.0-SN…

reverse笔记

一&#xff0c;strcat的使用方法&#xff08;在攻防世界中刷题时遇到的&#xff09; 二&#xff0c;壳&#xff08;做题遇到过但是一直不是很理解&#xff0c;今天查了一下&#xff09; 壳是一种软件保护技术&#xff0c;能够防止程序被轻易地分析和修改。 总而言之&#xff0…

spring4第7-8课-AOP的5种通知类型+切点定义详解+执行顺序

继续学习&#xff0c;方便自己复查记录 ①AOP简介&#xff1a; 面向切面编程(也叫面向方面编程)&#xff1a;Aspect Oriented Programming(AOP)。 Spring框架中的一个重要内容。。 通过预编译方式和运行期间动态代理实现在不修改源代码的情况下给程序动态统一添加功能…

EscapeX:去中心化游戏,开启极限娱乐新体验

VEX 平台推出全新去中心化游戏 EscapeX&#xff08;数字逃脫&#xff09;&#xff0c;创新性地将大逃杀玩法与区块链技术相融合。用户不仅能畅享紧张刺激的解谜过程&#xff0c;更能在去中心化、公正透明的环境中参与游戏。EscapeX 的上线&#xff0c;为 VEX 生态注入全新活力&…

Multi Agents Collaboration OS:Web DeepSearch System

背景&#xff1a;多智能体协作驱动网络信息处理的范式革新 随着大型语言模型&#xff08;LLM&#xff09;能力的突破性进展&#xff0c;人工智能正从“单点赋能”向“系统协同”演进。传统单一智能体在复杂业务场景中逐渐显露局限&#xff1a;面对需多维度知识整合、动态任务拆…

React 第五十三节 Router中 useRouteError 的使用详解和案例分析

前言 useRouteError 是 React Router v6.4 引入的关键错误处理钩子&#xff0c;用于在 路由错误边界&#xff08;Error Boundary&#xff09; 中获取路由操作过程中发生的错误信息。 它提供了优雅的错误处理机制&#xff0c;让开发者能够创建用户友好的错误界面。 一、useRou…

[arthas]arthas安装使用

arthas是阿里开源的一个java线上监控以及诊断工具&#xff0c;在docker容器中我们无需重启服务&#xff0c;也不用更改代码&#xff0c;就可以完成对应用内存、线程、日志级别的修改、方法调用的出入参、异常监测、执行耗时等&#xff0c;xxxx.xxxx.xxxxx为脱敏内容 1. 在docke…

Flask-Babel 使用示例

下面创建一个简单的 Flask-Babel 示例&#xff0c;展示如何在 Flask 应用中实现国际化和本地化功能。这个示例将包括多语言支持&#xff08;中文和英文&#xff09;、语言切换功能以及翻译文本的使用。 项目结构 我们将创建以下文件结构&#xff1a; 1. 首先&#xff0c;创…