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
相关推荐
微露清风9 小时前
系统性学习Linux-第二讲-基础开发工具
linux·运维·学习
不会代码的小猴9 小时前
Linux环境编程第六天笔记--system-V IPC
linux·笔记
阳光九叶草LXGZXJ9 小时前
达梦数据库-学习-48-DmDrs控制台命令(同步之Manager、CPT模块)
linux·运维·数据库·sql·学习
诸神缄默不语9 小时前
Linux命令行教程
linux
i建模12 小时前
如何在Arch Linux中重设忘记的root密码
linux·运维·服务器
kida_yuan13 小时前
【Linux】运维实战笔记 — 我常用的方法与命令
linux·运维·笔记
@syh.13 小时前
【linux】进程控制
linux
何中应15 小时前
vmware的linux虚拟机如何设置以命令行方式启动
linux·运维·服务器
江畔何人初15 小时前
kubernet与docker的关系
linux·运维·云原生
百炼成神 LV@菜哥15 小时前
Kylin Linux V10 aarch64 安装启动 TigerVNC-Server
linux·服务器·kylin