shell脚本编程(六)

shell脚本编程(五)https://blog.csdn.net/xiaochenXIHUA/article/details/156825515

一、shell中的判断

1.1、简单的if结构

bash 复制代码
#简单的if结构语法
if expression
then
    command
    command
    ......
fi

在使用这种简单if结构时,要特别注意【if 测试条件后】若没有使用分号【;】则【then】语句要换行,否则会产生不必要的错误。如果if与then处于同一行,则必须使用分号分隔,如下所示:

bash 复制代码
if expression;then
    command
    command
    ......
fi

简单的if结构是【单分支】当"条件成立"时执行相应的操作,执行流程图如下:

bash 复制代码
#简单if结构示例
vi testreply.sh

#【testreply.sh】文件的完整内容:
#!/bin/bash
#filename:testreply.sh
echo "你确定选择计算机专业?"
read reply
#在if 的条件判断部分使用扩展的test语句[[]]
#在[[]]中可以使用shell通配符进行条件匹配
if [[ $reply == [Yy]* || $reply == [Mm]aybe ]];then
        echo "你的选择是【$reply】"
fi


#执行这个脚本
bash testreply.sh

#调试脚本命令
bash -x testreply.sh 

1.2、if/else结构

bash 复制代码
#if/else结构语法
if expression1
then
    command
    command
    ......
else
    command
    command
    ......
fi

if/else命令是双向选择语句,当用户执行脚本时,若不满足if后的表达式也会转到else后的命令执行,具有较好的交互性。

if/else结构是【双分支】当"条件成立"、"条件不成立"时分别执行不同操作,执行的流程图如下:

bash 复制代码
#if/else结构示例
vi test-host-is-up-down.sh

#【test-host-is-up-down.sh】文件的完整内容:
#!/bin/bash
#filename:test-host-is-up-down.sh
#if条件部分可以使用普通命令测试
#当命令正确执行($?=0)时返回真,否则($?<>0)返回假
#ping命令中【-c1】表示只发送 1 个 ping 包;【-w2】表示超时时间为 2 秒
myhost=coffeemilk.blog.csdn.net
if ping -c1 -w2 $myhost &>/dev/null
then
        echo "$myhost is up"
else
        echo "$myhost is down"
fi


#执行脚本
bash test-host-is-up-down.sh

#调试脚本,可以查看到更多细节
bash -x test-host-is-up-down.sh

|--------|------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 序号 | 命令或参数 | 说明 |
| 1 | 在Linux/Unix系统中,进程启动时会默认打开3个标准文件描述符(文件句柄): 《1》【0】标准输入(stdin):默认对应键盘输入,程序从这里读取输入数据; 《2》【1】标准输出(stdout):默认对应终端窗口,程序的正常执行结果(如:echo输出、命令正常返回内容)都会输出到这里。 《3》【2】标准错误(stderr):默认对应终端窗口,程序的错误信息(如:命令不存在、参数错误)都会输出到这里。 ||
| 2 | >/dev/null 2>&1 | 这是两个连续的重定向操作,执行时有先后顺序: 《1》【>/dev/null】等价于【1>/dev/null】含义是:将程序的标准输出重定向到/dev/null中(/dev/null是Linux的"空设备"也叫"黑洞",任何写入到这里的数据都会被直接丢弃,不会留存也不会输出到终端中)。 《2》【2>&1】表示将标准错误重定向到标准输出当前所指向的目标(其中1前面的&符号不能省略)。 由于执行顺序是先执行【1>/dev/null】然后在执行【2>&1】因此呈现的效果是:标准输出与标准错误的输出都会被丢弃,不会显示在终端上。 |
| 3 | &>/dev/null | 这是Bash shell提供的简化语法糖,含义也是:直接将标准输出和标准错误同时重定向到/dev/null中丢弃,不会显示在终端上。 这个命令的功能与【>/dev/null 2>&1】完全一致,只是写法更加简洁。 |
| 【>/dev/null 2>&1】命令的兼容性更好,是POSIX标准规范的写法。适用于所有符合POSIX标准的shell (如:Bash、Sh、Ksh、Zsh等)。即使在非Bash环境(如:系统默认的/bin/sh,很多系统中的sh是dash软链接,不支持&>)也能正常运行【推荐在编写可移植性要求较高的脚本中使用(如:系统初始化脚本、跨环境运行的脚本)】。 【&>/dev/null】是Bash的专属简化写法,只能在Bash shell中有效。不兼容POSIX标准,在sh、dash等非Bash环境中执行会报错【推荐仅在Bash环境中允许的脚本使用(如:个人使用的脚本,明确指定#!/bin/bash作为解释器的脚本)】。 |||
[丢弃命令解析]

bash 复制代码
#if/else示例二
vi idcheck.sh

#【idcheck.sh】脚本的完整内容:
#!/bin/bash
## filename:  idcheck.sh
# purpose: check user id to see if user is root.
# Only root has a uid of 0.
# Format for id output: 
#   uid=9496(ellie) gid=40 groups=40
#   root's uid=0 
#
id=`id | awk -F'[=(]'  '{print $2}'`   # get user ID
echo "your user id is: $id"
if  (( id == 0 ))    # [ $id -eq 0 ]
then  
  echo "you are superuser."
else
  echo "you are not superuser." 
fi


#执行脚本
bash idcheck.sh

二、if/elif/else结构

bash 复制代码
if/elif/else结构语法
if expr1            #若expr1为真(返回值为0)
then                #那么
    commands1       #执行语句块commands1
elif expr2          #若expr1为假,而expr2为真
then                #那么
    commands2       #执行语句块commands2
    ......          #可以有多个elif语句
else                #else最多只能有一个
    commands6       #执行语句块commands6
fi                  #if语句必须以单次fi终止

|--------|-----------------------------------------------------------------|
| 序号 | 说明 |
| 1 | if语句必须以【fi】结束 |
| 2 | 【elif】可以有任意多个(0个或多个) |
| 3 | 【else】最多只能有一个(0个或1个) |
| 4 | 【if】语句可以嵌套使用 |
| 5 | 【expr】通常为条件测试表达式;也可以是多个命令,以最后一个命令的退出状态为条件值。 |
| 6 | 【commands】为可执行语句块,如果为空,需使用shell提供的空命令【冒号 :】该命令不做任何事情,只返回一个退出状态0 |
[if/else判断的一些注意项]

if/elif/else语句结构是【多分支】可针对多个条件执行不同操作,执行流程图如下:

bash 复制代码
#if/elif/else结构示例
vi ask-age.sh

#【ask-age.sh】文件的完整内容:
#!/bin/bash
#filename:ask-age.sh
read -p "你现在是几岁?" age
#使用shell算术运算符(())进行条件测试
if ((age<0||age>120));then      #[[ age < 0 || age > 120 ]]
        echo "超过年龄限制!"
        exit 1
fi
if ((age>=0&&age<7 ));then
        echo "儿童"
elif ((age>=7&&age<18));then
        echo "少年"
elif ((age>=18&&age<40));then
        echo "青年"
elif ((age>=40&&age<65));then
        echo "中年"
elif ((age>=65&&age<100));then
        echo "老年"
else
        echo "百岁老人"
fi


#执行脚本
bash ask-age.sh
bash 复制代码
#if嵌套语句示例一:
vi existuser.sh

#【existuser.sh】脚本的完整内容:
#!/bin/bash
#filename:existuser.sh
#if语句的嵌套使用(【$#】用于判断参数的个数;【$1】获取第一个参数;【$0】获取脚本名称)
if [ $# -eq 1 ] #或者使用[[ $# -eq 1 ]] 或(($#==1))
then
        if who | grep $1 >/dev/null;then
                echo $1 is active
        else
                echo $1 is not active
        fi
else
        echo "用法:$0 <username>"
        exit 1
fi


#执行脚本
chmod +x ./existuser.sh
./existuser.sh coffeemilk


#调试脚本
bash -x ./existuser.sh
bash 复制代码
#if嵌套示例二:
vi filetype.sh

#【filetype.sh】文件的完整内容:
#!/bin/bash
#filename:filetype.sh
#if的嵌套使用

file=$1
#【$#】是获取参数的个数【$# -ne 1】表示获取到的参数个数不等于1时返回0为真【&&】表示逻辑运算与
[ $# -ne 1 ] &&  echo "用法:$0 <filename>" && exit 1

if [ -d $file ];then
        echo "$file is a directory"
elif [ -f $file ];then
        if [ -r $file -a -w $file -a -x $file ];then
        # if [[ -r $file && -w $file && -x $file ]] ;then
                echo "你对【$file】拥有可读可写可执行【rwx】权限"
        fi
else
        echo "$file 不是一个目录或者一个文件!"
fi


#执行脚本
bash filetype.sh /etc

#调试脚本
bash -x filetype.sh /etc

三、case选择语句

bash 复制代码
#case选择语句的语法
case expr in        #expr为表达式,关键词in不要忘记
    pattern1)       #若expr与pattern1匹配(注意pattern1后的右括号)
        commands1   #执行语句块commands1
        ;;          #跳出case结构
    pattern2)       #若expr与pattern2匹配
        commands2   #执行语句块commands2
        ;;          #跳出case结构
    ......          #可以有任意多个模式匹配
    *)              #若expr与上面的模式都不匹配
        commands    #执行语句块commands
        ;;          #跳出case结构
esac                #case语句必须以esac终止

case选择语句的执行流程图如下:

|--------|--------------------------------------------------------------|
| 序号 | 说明 |
| 1 | 表达式【expr】按顺序匹配每个模式,一旦有一个模式匹配成功,则执行该模式后面的所有命令,然后退出case。 |
| 2 | 如果【expr】没有找到匹配的模式,则执行缺省值【*)】后面的命令块(类似于if中的else);【*)】可以不出现。 |
| 3 | 所给的匹配模式【pattern】中可以含有通配符和【|】。 |
| 4 | 每个命令块的最后必须有一个双分号【;;】可以独占一行,或放在最后一个命令的后面。 |
[case选择语句的一些注意项]

bash 复制代码
#case选择语句示例
vi favorite-language.sh

#【favorite-language.sh】文件的完整内容
#!/bin/bash
#filename:favorite-language.sh
echo "你最喜欢哪个脚本语言:"
echo "1)bash"
echo "2)perl"
echo "3)python"
echo "4)ruby"
echo "5)我不知道"

read lang
readonly tip="你选择了"
case $lang in
        1) echo "$tip【bash】";;
        2) echo "$tip【perl】";;
        3) echo "$tip【python】";;
        4) echo "$tip【ruby】";;
        5) echo "$tip【我不知道】";;
esac


#执行脚本
bash favorite-language.sh

#调试脚本
bash -x favorite-language.sh
bash 复制代码
#case选择的示例二
vi yesorno.sh

#【yesorno.sh】文件的完整内容
#!/bin/bash
## filename: yesorno.sh
echo -n "Do you agree with this? [yes or no]: " 
read yn
case $yn in
  [Yy] | [Yy][Ee][Ss]) 
		echo "Agreed."  
		;;
  [Nn] | [Nn][Oo])   
                 echo "Not agreed."
                 exit 1
                 ;;
   *)            
		echo "Invalid input." 
		;;
esac


#测试脚本
bash yesorno.sh
bash 复制代码
#case选择的示例三
vi backup.sh

#【backup.sh】文件的完整内容:
#!/bin/bash
## filename: backup.sh
# A shell script to backup mysql, webserver and files.
# opt=$1
case $1 in
   sql) echo "Running mysql backup using mysqldump tool..." ;;
  sync) echo "Running backup using rsync tool..."           ;;
   git) echo "Running backup using gistore tool..."         ;;
   tar) echo "Running tape backup using tar tool..."        ;;
     *) 
        echo "Backup shell script utility"
        echo "Usage: $0 {sql|sync|git|tar}"
        echo "	sql  : Run mySQL backup utility."
        echo "	sync : Run web server backup utility."	
        echo "	git  : Run gistore backup utility."	
        echo "	tar  : Run tape backup utility." 
        ;;
esac


#执行脚本
bash backup.sh
bash 复制代码
#case选择语句的示例四
vi disktest.sh

#【disktest.sh】文件的完整内容:
#!/bin/bash
## filename: disktest.sh
# This script does a very simple test for checking disk space.
max_usage=$(LANG=C df -Ph | awk '{print $5}' | grep % | grep -v Use | sort -n | tail -1 | cut -d "%" -f1)
mountlabel=`LANG=C df -Ph|awk '{print $5,$6}'|grep -v Use|sort -n|tail -1|awk '{print $2}'`
case ${max_usage} in
[1-6]*)    
	MSG="All is quiet."   
	;;
[7-8]*)
  	MSG="Start thinking about cleaning out some stuff. "
  	MSG="$MSG There's a partition ${mountlabel} is ${max_usage}% used." 
	;;
9[1-8])
  	MSG="Better hurry with that new disk... "  
  	MSG="$MSG One partition is ${max_usage}% used."  
	;;
99)
  	MSG="I'm drowning here!  There's a partition at ${max_usage}% used"  
	;;
*)
  	MSG="I seem to be running with an nonexitent amount of disk space..."  
	;;
esac
#echo $MSG | mail -s "disk report `date`" root
echo $MSG

#执行脚本
bash disktest.sh
相关推荐
sim20202 小时前
创建FTP账号
linux
Ha_To2 小时前
2026.1.12 Linux提升账户权限
linux·运维·服务器
OopspoO2 小时前
Linux内存分析工具
linux·运维
oMcLin2 小时前
如何在Ubuntu 20.04上配置并调优Kubernetes集群,确保在多租户环境下的高可用性与资源分配?
linux·ubuntu·kubernetes
石头5302 小时前
Service 详解
linux
小鸡脚来咯2 小时前
Linux 服务器问题排查指南(面试标准回答)
linux·服务器·面试
末日汐3 小时前
磁盘与文件系统
linux·运维·数据库
水天需0103 小时前
Linux PS4 环境变量详解
linux
小新ya3 小时前
vscode增删改查文件,一直等待中...
linux·vscode