shell脚本的条件判断式

news2024/9/27 21:25:56

文章目录

  • shell脚本的条件判断式
    • 利用 if...then
      • 单层、简单条件判断式
      • 多重、复杂条件判断式
        • 例题1
        • 例题2
    • 利用case...esac判断
      • 例题1
    • 利用function功能
      • 例题1

shell脚本的条件判断式

很多时候我们必须要根据某些数来判断程序该如何举例来说,我们在之前的练习中让用户输入Y/N的时候,必须要执行不同的信息输入,可以使用&& 和||的方式,那么如果我们要执行一堆命令呢?真的要if then 来帮忙。

利用 if…then

这个if…then是最常见的条件判断式了。简单来说,当符合某个条件判断的时候,就允许他进行某项任务。这个if…then的判断还有多层次的情况。

单层、简单条件判断式

如果你只有一个判断式要进行。那么我们可以简单地这样看:

if  [ 条件判断式 ]; then
         当条件成立时,可以进行的命令工作内容
fi  # 将if 反过来写,就成为fi,意思就是结束if

如果我们有多个条件判别的话,就像之前的案例所写的,就是将【多个条件写入一个中括号内的情况】,我们还可以有多个括号隔开。而括号和括号之间,则以&&或||隔开

  • &&代表AND
  • ||代表or

所以我们之前使用中括号判别到底输入的是不是Y/y,就可以这样修改

[ "${yn}" == "Y" -o "${yn}" == "y" ]

上面的案例可以替换为

[ "${yn}" == "Y" ] || [ "${yn}" == "y" ]

那么我们再来用if…then的样式来看看:

image-20230430150507499

上图是我们之前案例的脚本内容我们来做一下修改

[root@localhost shelldir]# vim continue.sh
#!/bin/bash
# 程序说明:
#  这个程序就是让用户做选择
# 时间:
# 2023/04/30
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:~/shelldir
export PATH
read -p "请输入(Y/N):" yn
if [ "${yn}" == "Y" ] || [ "${yn}" == "y" ]; then
           echo -e "\n您输入了Y/y,请继续"
           exit 0
fi
if [ "${yn}" == "N" ] || [ "${yn}" == "n" ]; then
           echo -e "\n您输入了N/n,请退出"
           exit 0
fi
echo -e "没有识别到您输入了什么,重新输入\a" && exit 0

执行结果(输入Y看结果)

[root@localhost shelldir]# sh continue.sh 
请输入(Y/N):Y

您输入了Y/y,请继续

执行结果(什么也没输入)

[root@localhost shelldir]# sh continue.sh 
请输入(Y/N):
没有识别到您输入了什么,重新输入

你可能会问,上述案例写的这么复杂没有之前的代码简单,但是如果你以逻辑概念来看,其实上面的范例中,我们使用了两个条件判断,明明仅有一个${yn}的变量,为什么要进行两次比对呢?我们再来用多重条件判断式来试试

多重、复杂条件判断式

就像上述例子一样,如果该数据需要进行多种不同的判断,我只想执行一次${yn}的判断就好,不想做多次if的判断,那样应该怎么做呢?

一个条件判断,分成功执行与失败执行(else)

if [ 条件判断式 ]; then
      当条件判断式成立时,可执行的命令
else
      当条件判断式不成立时,可执行的命令
fi

如果你遇到非常复杂的判断情况,则可以使用这个语法

if [ 条件判断式 ]; then
      当条件判断式成立时,可执行的命令
elif [ 条件判断式2 ]; then
       当条件判断式2成立时,可执行的命令
else 
       当条件判断式1与2均不成立时,可执行的命令
fi

要注意的是,【elif】也是个判断式,因此【elif】后面都要接then来处理。else则是最后没有成立的结果,不用加then。我们可以将之前的案例改为

#!/bin/bash
# 程序说明:
#  这个程序就是让用户做选择
# 时间:
# 2023/04/30
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:~/shelldir
export PATH
read -p "请输入(Y/N):" yn
if [ "${yn}" == "Y" ] || [ "${yn}" == "y" ]; then
                 echo -e "\n 您输入了Y/y,请继续"
elif [ "${yn}"  == "N" ] || [ "${yn}" == "n" ]; then
                 echo -e "\n 您输入了N/n,请退出"
else
                 echo -e "\n我不知道你输入的是什么,重新输入\a"
fi

程序是不是变得非常容易看懂了,可以避免重复判断的状况。

例题1

一般来说,如果你不希望用户键盘输入额外的数据,则可以使用【$1】参数功能,让用户执行命令时将参数带进去。现在我想让用户输入【hello】这个关键字时,利用参数的方法可以这样依序设计

  1. 判断$1是否为hello,如果是的话,就显示"你好,最近过的好吗?"
  2. 如果没有加任何参数,就提示用户必须要使用的参数执行法;
  3. 而如果加入的参数不是hello,就提醒用户仅能使用hello为参数。
[root@localhost shelldir]# vim howareyou.sh 
# 程序说明:
#    检查在运行程序的时候后面是否跟了参数 hello
# 时间:
# 2023/04/30
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:~/shelldir
export PATH
if [ "${1}" == "hello" ]; then
   echo -e "\n你好,最近过的好吗?\a"
elif [ -z  "${1}"  ]; then
   echo -e "\n请在运行的程序后面添加【hello】这个参数, 例如:sh ${0} hello"
else
   echo -e "\n您添加的参数错了,请添加hello这个参数, 例如:sh ${0} hello"
fi

执行结果(输入hello)

[root@localhost shelldir]# sh howareyou.sh hello

你好,最近过的好吗?

执行结果(什么也没输入)

[root@localhost shelldir]# sh howareyou.sh

请在运行的程序后面添加【hello】这个参数, 例如:sh howareyou.sh hello

执行结果(随便添加了一个参数)

[root@localhost shelldir]# sh howareyou.sh ppp

您添加的参数错了,请添加hello这个参数, 例如:sh howareyou.sh hello

接下来再来了解一个命令利用这个命令来做几个实验,学一个叫netstat的命令,这个命令可以查询到目前主机开启的网络服务端口,利用【netstat -tuln】来获取目前主机启动的服务

如果没有netstat这条命令可以使用

yum install -y net-tools来安装相关的命令

[root@localhost ~]# netstat -tuln 
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN     
tcp6       0      0 :::22                   :::*                    LISTEN     
tcp6       0      0 ::1:25                  :::*                    LISTEN     
udp        0      0 127.0.0.1:323           0.0.0.0:*                          
udp6       0      0 ::1:323                 :::*    

输出的内容中,最重要的就是 【Local Address(本地主机的IP与端口对应)】那个字段,它代表的是本机所启动的网络服务,IP的部分说明的是该服务器位于哪个接口上。若为【127.0.0.1】则是针对本机开发,若是【0.0.0.0】或【:::】则代表对整个internet开放。每个端口都有其特点的网络服务,几个常见的端口与相关网络服务的关系是:

  • 80:WWW
  • 22:ssh
  • 21:ftp
  • 25:mail
  • 111:RPC(远程过程调用)
  • 631:CPUS(打印机服务功能)

假设我的主机要检测比较常见的21、22、25及80端口时,那我如何通过netstat去检测我的主机是否开启了这四个主要的网络服务端口?由于每个服务的关键词都是接在冒号【:】后面,所以可以使用类似【:80】的方式来检测

[root@localhost shelldir]# vim netstat.sh 
# 程序说明:
#     使用netstat和grep进行检测 21、22、25及80端口是否存在
# 时间:
# 2023/04/30
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:~/shelldir
export PATH
testfile=/root/netstatcheck.txt
netstat -tuln > ${testfile}
testing=$(grep ":80" ${testfile})
if [ "${testing}" != ""  ]; then
    echo "存在80端口"
fi
testing=$(grep ":25" ${testfile})
if [ "${testing}" != ""  ]; then
    echo "存在25端口"
fi
testing=$(grep ":22" ${testfile})
if [ "${testing}" != ""  ]; then
    echo "存在22端口"
fi
testing=$(grep ":21" ${testfile})
if [ "${testing}" != ""  ]; then
    echo "存在21端口"
fi

例题2

条件判断式还可以搞的更复杂。举例来说,每当过年的时候都能收到压岁钱,写个脚本,每当我输入过年的时间的时候,都会提示我还有几个月过年。

  1. 先让用户输入过年的时间
  2. 用现在的时间对比过年时间
  3. 计算出离过年还剩下多少天

可以利用【date --date=“YYYYMMDD”+%s】转成秒数后,就很容易操作了

[root@localhost shelldir]# vim  guonian.sh 
#!/bin/bash
# 程序说明:
#      此程序是计算离过年还需要多长时间的
# 时间:
#    2023/04/29
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:~/shelldir
export PATH
# 用户输入过年时间判断是否为空以及是否为8个字符
read -p "请输入过年的时间,我帮你计算剩下多长时间过年如:(20240101):" date
date_panduan=$( echo ${date} | grep -E '^[0-9]{8}$' )
if [ "${date_panduan}" == "" ]; then
       echo -e "\n请输入正确的日期\a"
       exit 1
fi
# 计算出过年的时间
declare -i date_ustdin=$( date --date="${date_panduan}" +%s)
declare -i date_xianzai=$( date +%s)
declare -i date_jian=$((${date_ustdin} - ${date_xianzai}))
declare -i date_hsstdin=$( echo ${date_jian} /60/60/24 | bc)
# 输出现在离过年还需要多长时间
echo -e "距离过年还剩下"${date_hsstdin}"天"

上面的程序可以计算离过年还剩下多少天。其中的【${date_hsstdin}】变量中的 /60/60/24 就是将秒数换算成天数。

执行结果

[root@localhost shelldir]# sh guonian.sh 
请输入过年的时间,我帮你计算剩下多长时间过年如:(20240101):20240101
距离过年还剩下242天

利用case…esac判断

上面提到的【if … then … fi】对于变量的判断是以【比对】的方式来分辨的,如果符合状态就进行某些操作,并且通过较多层次(就是 elif …)的方式来进行多个变量的程序代码编写。【case…esac】语句用于对变量或参数多重比较,如果匹配成功,就执行一段语句,否则执行其他语句。

它的语法格式如下

case  $变量名称 in         # 关键字为case,还有变量前面有美元符号
  "第一个变量内容")         # 每个变量内容建议用双引号括起来,关键字则为右圆括号
         程序段            
           ;;             # 买个类别结尾使用两个连续的分号来处理
  "第二个变量内容")
         程序段
           ;;
  *)                      # 最后一个变量内容都会用*来代表所有其他值
           exit 1
           ;; 
esac                      # 最终的case结尾,是【case】反过来写。

来修改以下上述的例题1,他应该会变成这样

#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:~/shelldir
export PATH
case ${1} in
    "hello")
      echo "Hello,how,are,you?"
       ;;
    "")
      echo "你没有加参数hello例如:sh  ${0} command"
       ;;
    *)    # 相当于通配符,0~无穷多个任意字符的意思
      echo "你参数输入错了,应该输入hello"
       ;;
esac

执行结果

[root@localhost shelldir]# sh howareyou.sh 
你没有加参数hello例如:sh  howareyou.sh command
[root@localhost shelldir]# sh howareyou.sh dwda
你参数输入错了,应该输入hello
[root@localhost shelldir]# sh howareyou.sh hello
Hello,how,are,you?

我们Linux的【/etc/init.d】目录下有许多服务。例如有个名为netconsole的服务在该目录下,那么你想要重启该服务,可以这样做(要用root身份)

[root@localhost init.d]# /etc/init.d/netconsole restart

重点是restart,如果你使用【less /etc/init.d/netconsole】去查看一下,就会看到它使用的是case语法,并且会规定某些既定的变量内容。你可以执行/etc/init.d/netconsole,该脚本会告诉你有哪些后续接的变量可以使用。

一般来说,使用【case ${变量} in】这个语法时,当中的那个【${变量}】大致有两种获取方式:

  • 直接执行式:例如上面提到的,利用【howareyou.sh hello】的方式来直接给予$1这个变量的内容,这也是在/etc/init.d/目录下的大多程序的设计方式
  • 交互式:通过read这个命令来让用户输入变量内容

例题1

让用户输入one、two、three并且将用户的变量显示到屏幕上;如果输入的不是one、two、three就告诉用户只有这三种选择

这个是直接执行式

#!/bin/bash
# 程序说明:
#      直接执行程序,程序后面只能跟one、two、three三个参数
# 时间:
# 2023/04/30
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:~/shelldir
export PATH
case ${1} in
   "one")
     echo "这是参数one"
     ;;
   "two")
     echo "这是参数two"
     ;;
   "three")
     echo "这是参数three"
     ;;
   *)
     echo "请输入"one,two,three"这些参数"
     ;;
esac

这个是交互式

#!/bin/bash
# 程序说明:
#     用户输入一个参数,程序判断有没有这个参数
# 时间:
# 2023/04/30
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:~/shelldir
export PATH
read -p "请选择参数:" choice
case ${choice} in
   "one")
     echo "这是参数one"
     ;;
   "two")
     echo "这是参数two"
     ;;
   "three")
     echo "这是参数three"
     ;;
   *)
     echo "请输入"one,two,three"这些参数"
     ;;
esac

利用function功能

什么是【函数(function)】功能?简单来说,其实,函数可以在shell脚本当中做出一个类似自定义执行命令的东西,最大的功能就是可以简化我们很多的程序代码。举例来说,上面的案例中,每个输入结果one、two、three其实输出的内容都一样,那么我就可以使用function来简化

function的语法是这样的

function fname () {
       程序段
}

那个fname就是我们自定义的执行命令名称,而程序段就是我们要它执行的内容了。要注意的是,shell脚本的执行方式是由上到下,从左至右,因此在shell脚本当中的function的设置一定要在程序的最前面,这样才能够在执行时被找到可用的程序段

例题1

我们将上述的case…esac的例题改一下,自定义一个名为printit的函数来使用:

[root@localhost shelldir]# sh function.sh
#!/bin/bash
# 程序说明:
#    使用function来选择参数
# 时间:
# 2023/04/30
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/shelldir
export PATH
function printit () {
      echo -n "你选择的参数为:"    # 加上-n可以不换行继续在同一行显示
}
echo "这是程序打印出你选择的参数:"
case ${1} in
   "one")
     printit; echo ${1} | tr 'a-z' 'A-Z'  # 将输出的参数大小写转换
      ;;
   "two")
     printit; echo ${1} | tr 'a-z' 'A-Z'
      ;;
   "three")
     printit; echo ${1} | tr 'a-z' 'A-Z'
      ;;
    *)
     echo "你只能选择${0} {one|two|three}"
      ;;
esac

上面的例子中,声明了一个函数 prinit ,所以,当我们在后续的程序段中,只要执行printit的话,就表示我的shell脚本要去执行【function printit】里面的那几个程序段。

另外,function也拥有内置变量的,它的内置变量与shell脚本很类似,函数名称$0,后续接的变量也是以$1、$2..来替换,【function fname () {程序段}】内的$0,$1…等与shell脚本的$0是不同的。

以上面的例题1来改变一下进行说明,假如我执行【sh function.sh one】,表示shell脚本内的$1为"one"这个字符串,但是在printit( )内的$1则与这个one无关。

#!/bin/bash
# 程序说明:
#    使用function来选择参数
# 时间:
# 2023/04/30
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/shelldir
export PATH
function printit () {
      echo -n  "你选择的参数为:${1}"
}
echo "下面的程序会在屏幕上展示你可以选择的参数"
case ${1} in
   "one")
     printit 1
      ;;
   "two")
     printit 2
      ;;
   "three")
     printit 3
      ;;
    *)
     echo "你只能选择${0} {one|two|three}"
      ;;
esac

在上面的例子中,如果你输入【sh function.sh one】就会出现【你选择的参数为:1】如下图

image-20230504105203965

因为我们在程序段落中,我们写了【printit 1】,那个1就会称为function当中的$1。

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

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

相关文章

jsp网上拍卖管理系统统Myeclipse开发mysql数据库web结构jsp编程计算机网页项目

一、源码特点 jsp网上拍卖管理系统是一套完善的java web信息管理系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5.0&a…

AWS Lambda - 第一部分

Hello大家好,我们今天开始讨论AWS Lambda的内容。 SAP认证考试会涉及到很多Lambda的内容,想要通过认证考试虽然不一定非要精通开发,但需要知道Lambda的一些功能和特性、适用场景以及Lambda是如何工作的。 我们开始吧! Lambda与…

数据结构刷题(三十):96不同的二叉搜索树、01背包问题理论、416分割等和子集

一、96. 不同的二叉搜索树 1.这个题比较难想递推公式, dp[3],就是元素1为头结点搜索树的数量 元素2为头结点BFS的数量 元素3为头结点BFS的数量 元素1为头结点搜索树的数量 右子树有2个元素的搜索树数量 * 左子树有0个元素的搜索树数量 元素2为头结…

AWS Lambda - 第二部分

Hello大家好,我们今天继续讨论AWS Lambda的内容。 Lambda的网络 首先,我们来讨论一下Lambda的网络,联网相关的内容。 在部署Lambda时,在默认情况下,Lambda函数是部署和运行在AWS的一个安全的VPC中,是在您…

“大运”有我丨智安网络护航大运,荣获成都市公安局感谢信!

近日,深圳市智安网络有限公司四川分公司(以下简称“智安网络”)荣幸受邀参与第31届世界大学生夏季运动会网络安全检查工作,对中和体育中心场馆安全漏洞检测进行现场技术支撑。 智安网络对此次网络安全检查工作高度重视&#xff0…

PySpark基础入门(2):RDD及其常用算子

更好的阅读体验:PySpark基础入门(2):RDD及其常用算子 - 掘金 (juejin.cn) 目录 RDD简介 RDD Coding RDD简介 RDD(Resilient Distributed Dataset),是一个弹性分布式数据集,是Sp…

带你快速入门光模块行业

一、行业介绍 光纤通信(简称光通信)是利用光导纤维传输光波信号的一种通信方式,于上世纪六七十年代由华裔科学家高锟博士等人率先提出。 光通信是以激光作为信息载体,以光纤作为传输媒介的通信方式,现已取代电通信成…

if __name__ == “__main__“: 理解

if __name__ "__main__": 是 Python 中常用的一种条件判断语句,主要作用是在当前模块作为程序入口时执行一些特定的代码,而在被其它模块引入时不执行这些特定的代码。 具体来说,当一个 Python 模块被导入时,Python 解…

关注度拉满,RSAC 2023 热门安全工具速览

RSAConference2023于当地时间4月24日在旧金山正式拉开帷幕。自上届RSAC以来,网络安全行业发生了巨大的变化,尤其是以OpenAI聊天机器人为代表的内容生成型AI的兴起,对网络防御和攻击的影响比以往任何时候都更加明显。 今年,与RSAC相…

数据结构之第十章、Java对象的比较

目录 一、PriorityQueue(堆)中插入对象 二、元素的比较 2.1基本类型的比较 2.2对象比较的问题 三、对象的比较 3.1覆写基类的equals 3.2基于Comparble接口类的比较 3.3基于比较器比较 3.4三种方式对比 3.5代码实现 四、集合框架中PriorityQu…

大型医院影像PACS系统三维重建技术(获取数据、预处理、配准、重建和可视化)

PACS(Picture Archiving and Communication System)系统作为医学图像的存储和传输平台,为医生和患者提供了便捷高效的诊疗服务支持。近年来,三维重建技术在PACS系统中的应用越来越广泛。 一、三维重建技术的基本原理 在PACS系统…

JS 中的 performance,测量web应用性能

文章目录 属性和方法performance.memory 内存performance.navigation 页面的来源信息performance.timing 时间消耗相关时间计算Performance.mark()performance.now() Web Performance API 允许网页访问某些函数来测量网页和 Web 应用程序的性能 performance 包含如下属性和方法…

Linux基础IO【软硬链接与动静态库】

✨个人主页: 北 海 🎉所属专栏: Linux学习之旅 🎃操作环境: CentOS 7.6 阿里云远程服务器 文章目录 🌇前言🏙️正文1、软硬链接1.1、基本认知1.2、实现原理1.3、应用场景1.4、取消链接1.5、ACM时…

JavaWeb ( 一 ) HTTP协议

1.http协议 1.0.Web Web指的是World Wide Web,也称为万维网,是一种基于互联网的信息系统,由全球数百万个网站组成。它允许用户通过使用网页浏览器访问和交互信息,例如阅读新闻、购物、发送和接收电子邮件、社交媒体等。 Web使用…

解密.[support2022@cock.li].faust后缀勒索病毒加密的文件:拯救您的企业数据的完整指南!

引言: 您的企业数据是您业务的核心。但是,当.[support2022cock.li].faust后缀勒索病毒突袭您的系统时,您的数据将遭受沉重打击。这种恶意软件利用高级加密算法,将您的文件锁定在无法访问的状态。在这篇详细的指南中,9…

tcp/ip

这里写自定义目录标题 线程 防止阻塞 123 windows下4 https://zhuanlan.zhihu.com/p/139454200 https://www.bilibili.com/video/BV1eg411G7pW/?spm_id_from333.337.search-card.all.click&vd_sourcee7d12c9f66ab8294c87125a95510dac9 with socket.socket() as s:s.bind(…

xcode Swift Log CocoaLumberjack

参考【iOS】CocoaLumberJack日志库集成 - 简书 logging - How to capture Device Logs in iOS during Runtime into a file in Documents Directory from iPhone? - Stack Overflow GitHub - apple/swift-log: A Logging API for Swift 如何导出日志 方法一发邮件&#xf…

Vue——Elementui案例实现

需求分析: 对于上面要仿照的页面先新建一个页面组件EmpView.vue组件在views文件夹下 基本页面布局 对于上面页面的布局其实在Element当中也可以找到相应可以实现的组件, 成功找到一个符合要求的布局,直接复制粘贴到项目里面 此时页面相应的位置已经有了对应的占位单…

自动化运维工具 Ansible

目录 Puppet 自动运维工具特点: Saltstack 自动运维工具特点: Ansible 自动运维工具特点: Ansible 运维工具原理 Ansible 管理工具安装配置 Ansible 工具参数详解 Ansible ping 模块实战 Ansible command 模块实战 Ansible copy 模块实战 Ansib…

uboot第二阶段 start_armboot函数代码分析

1.1、start_armboot函数简介 这个函数整个构成了uboot启动的第二阶段。 1.2、uboot第二阶段做的事情 uboot第一阶段主要就是初始化了SoC内部的一些部件(譬如看门狗、时钟、串口…),然后初始化DDR并且完成重定位。那么,uboot的第…