Shell 编程之条件判断与流程控制

发布于 2024-12-16 12:45:03 字数 9715 浏览 12 评论 0

两种判断格式

# 格式 1
test -e /root/test.sh
# 格式 2(推荐使用)
[ -e /root/test.sh ]
# 判断当前目录是否存在 test.py 文件,存在输出 0,不存在输出 1
➜  ~ [ -e ./test.py ] && echo 0 || echo 1
0
➜  ~ [ -e ./twwwest.py ] && echo 0 || echo 1
1


# 创建一个硬链接
ln /root/test.txt /temp/demo.txt
# 测试是否为同一个文件
[ /root/test.txt -ef /temp/demo.txt ] && echo yes || echo no
  • -nt: new time
  • -ot: old time
  • -ef: equal file 是否为相同的源文件

注意:-ef 应该只是能判断是不是链接,并不能判断软硬

  • -eq: equal 等于
  • -ne: not equal 不等于
  • -gt: greater than 大于
  • -lt: less than 小于
  • -ge: greater or equal 大于等于
  • -le: less or equal 小于等于


  • -a: -and
  • -o: -or
a=11
# 判断变量 a 是否有值,同时变量 a 的值是否大于 23
[ -n "$a" -a "$a" -gt 23 ] && echo yes || echo no

如何'背'程序

  • 抄写程序代码并能正确运行
  • 为程序补全注释
  • 删掉注释,为代码重新添加注释
  • 看注释写代码
  • 删掉代码和注释,从头开始写

单分支 if 条件语句

if [ 条件判断式 ]; then
	程序
fi
# 或者
if [ 条件判断式 ]
	then
	程序
fi

注意以下 3 点:

  • if 语句使用 fi 结尾,和一般语言使用大括号结尾不同
  • [ 条件判断式 ]就是使用 test 命令判断,所以中括号和条件判断式之间必须有空格
  • then 后面跟符合条件之后执行的程序,可以放在[]之后,用";"分割,也可以换行写入,就不需要";"了
# demo1(判断当前登录用户是否为 root)
# demo1.sh
#!/bin/bash

# 从环境变量中过滤出包含"USER"字符的行,结果为 USER=root; 然后使用字符串截取命令 cut,按 分隔符为"=",取第二列数据 的参数取出 root 值
test=$(env | grep "USER" | cut -d "=" -f 2)

# "=="是字符串判断是否相等命令 ps:[]里的数据,两边需要加空格,否则会报命令错误
if [ "$test" == "root" ]
	then
	echo "Current user is root"
fi
# demo2(判断分区使用率)
#!/bin/bash
#匹配出包含 sda5 的行,取分区使用率这一列(楼主是第五列),用 cut 按 "%"分割、取第一列的 参数取出根分区的使用率,赋值给变量 test
test=$(df -h | grep "sda5" | awk '{print $5}' | cut -d '%' -f 1)
#如果变量 test 大于等于 10,则输出
if [ "$test" -ge '10' ]
	then
	echo "/ is null"
fi

双分支 if 语句

if [条件判断式]
	then
		条件成立时执行的程序
	else
		条件不成立时执行的程序
fi
#!/bin/bash
#read:接收键盘输入;-t 秒数:read 命令会一直等待用户输入,使用此选项可以指定等待时间;-p:提示信息。
read -t 30 -p "please input the dir:" dir

#-d 判断是不是一个目录
if [ -d "$dir" ]
	then
		echo "输入的是目录"
	else
		echo "输入的不是目录"
fi
apache 服务:web 服务,www 服务
ps aux:查看系统中所有正在运行的进程,
apache 关键字 httpd
# 但是 ps aux | grep httpd 本身也会产生一条包含 httpd 的进程
# 搜索时去掉带有 grep 的结果
grep -v grep:取反,不包含 grep

判断 apache 服务是否启动:如果 ps aux | grep httpd | grep -v grep 有记录,则说明 apache 服务启动,否则没有启动。

#判断 apache 服务是否启动
test=$(ps aux | grep httpd | grep -v grep)
#定义变量 test,并且查找是否启动 apache 的结果赋值给 test
#ps aux:查看当前所有正在运行的进程
#grep httpd 过滤出 apache 进程
#grep -v grep 去掉包含 grep 的进程 -v 取反

if [ -n "$test" ]
#判断 test 是否为空
	then
#如果不为空则执行这段程序 把结果写入/tmp/autostart-acc.log 中
		echo " $(date) httpd is ok " >> /tmp/autostart-acc.log
	else
#如果为空这执行这段程序
#首先启动 httpd 服务
	/etc/rc.d/init.d/httpd start &>/dev/null
#然后把事件记录在错误日志中
	echo " $(date) httpd is no \n httpd is autostart now" >> /tmp/autostart-err.log
fi

多分支 if 语句

if [ 条件判断式 1 ]
	then
		当条件判断式 1 成立时执行的程序
elif [ 条件判断式 2 ]
	then 
		当条件判断式 2 成立时执行的程序
...省略更多条件
else 
	当所有条件都不成立时执行此程序
fi
# demo(计算器)
#!/bin/bash
#通过 read 命令接收要计算的数值,并赋予变量 num1 和 num2
read -t 30 -p "Please input number1: " num1
read -t 30 -p "Please input number2: " num2
#通过 read 命令接收要计算的符号,并赋予变量 ope
read -t 30 -p "Please input an oprator: " ope
#-o 表示或的意思即 or
if [ "$ope" == '+' -o "$ope" == '-' -o "$ope" == '*' -o "$ope" == '/' ]

then
	result=$(($num1$ope$num2))
	echo $result
else
	echo "Please input a valid oprator."
fi
#!/bin/bash

read -t 30 -p "Please input num1: " num1
read -t 30 -p "Please input num2: " num2
read -t 30 -p "Please input a operator: " ope
#第一层判断,用来判断 num1、num2 和 ope 中都有值
if [ -n "$num1" -a -n "$num2" -a -n "$ope" ]
	then
		#定义变量 test1 和 test2 的值为$(命令) 的结果
		#后续命令作用是:把变量 test1 的值替换为空。如果能替换为空,证明 num1 的值为数字
		#如果不能替换为空,证明 num1 的值为非数字。使用这种方法判断变量 num1 的值为数字
		#用同样的方法测试 test2 变量
		test1=$(echo $num1 | sed 's/[0-9]//g')
		test2=$(echo $num2 | sed 's/[0-9]//g')
		#第二层判断,用来判断 num1 和 num2 为数值
		#如果变量 test1 和 test2 的值为空,则证明 num1 和 num2 是数字
		if [ -z "$test1" -a -z "$test2" ]
			#如果变量 test1 和 test2 是数字,则执行以下命令
			then
				第三层判断用来确认运算符
				if [ "$ope" == '+' ]
					then
						res=$(($num1+$num2))
				elif [ "$ope" == '-' ]
					then
						res=$(($num1-$num2))
				elif [ "$ope" == '*' ]
					then
						res=$(($num1*$num2))
				elif [ "$ope" == '/' ]
					then
						res=$(($num1/$num2))
				else
					#如果运算符不匹配,提示输入有效的符号
					echo "Please enter a valid symbol"
					#并退出程序,返回错误代码 10
					exit 10
				fi
			else
				#如果 test1 和 test2 不是数值
				#则提示输入有效的数值
				echo "Please enter a valid value"
				#并退出程序,返回错误代码 11
				exit 11
		fi
	else
		echo "Please enter values"
		exit 12
fi
echo "$num1$ope$num2=$res"
#demo(判断用户输入的是什么文件)
#!/bin/bash
#接收键盘的输入,并赋予变量 filename
read -t 30 -p "please input a filename : " filename
#判断 filename 变量是否为空
if [ -z "$filename" ]
        then
        	echo "Error,please input a filename"
        	exit 1
#判断 filename 的值是否存在
elif [ ! -e  "$filename" ]
        then
        	echo "Your input is not a file"
			exit 2
#判断 filename 的值是否为普通文件
elif [ -f "$filename" ]
        then
        echo "$filename is a regulare file"
#判断 filename 的值是否为目录文件
elif [ -d "$filename" ]
        then
        echo "$filename is a directory"
else
        echo "$filename is an other file"
fi

多分支 case 语句

case 语句和 if...elif...else 语句一样都是多分支条件语句,不过和 if 多分支语句不同的是,case 语句只能判断一种条件关系,而 if 语句可以判断多种条件关系。

# 多分支语句 case 格式:
case $变量名 in
  "值 1")
       如果变量值等于值 1,执行程序 1
       ;;
  "值 2")
       如果变量值等于值 2,执行程序 2
       ;;
  ……
  ……
   *)
      如果变量值都不是以上值,则执行此程序
      ;;
esac
#case 实例,选择课程
#!/bin/bash

echo "1 :  yuwen"
echo "2 :  shuxue"
echo "3 :  yingyu"
read -t 30 -p "choose kecheng:" cho

case $cho in
        "1")
                echo "choose yuwen."
                ;;
        "2")
                echo "choose shuxue."
                ;;
        "3")
                echo "choose yingyu"
                ;;
        *)
                echo "choose wrong"
                ;;
esac

for 循环

#in 后面跟几个值,for 循环就执行几次
for 变量 in 值 1 值 2 值 3...
	do
		程序
	done
#!/bin/bash

for i in 1 2 3 4 5
	do
		echo $i
	done
#demo(批量解压缩包)
#!/bin/bash

cd /root/test

#覆盖
ls *.tar.gz > ls.log
#添加
ls *.tgz >> ls.log
for i in $(cat ls.log)
	do
		tar -zxvf $i & > /dev/null
	done
rm -rf ls.log
# 语法二
for((初始值;循环控制条件;变量变化))
	do
		程序
	done
#!/bin/bash
#从 1 加到 100

sum=0
for((i=1;i<=100;i=i+1))
	do
		sum=$(($sum+$i))
	done
echo "The sum of 1+2+...+100 is : $sum"
#批量添加指定数量的用户实例
#!/bin/bash
read -t 30 -p "input user name:" name
read -t 30 -p "input password:" pass
read -t 30 -p "input user number:" num
#检查输入内容是否为非空
if [ -n "$name" -a -n "$pass" -a -n "$num" ]
        then
#检查输入的用户数量是否为纯数字 
        chknum=$( echo "$num" | sed 's/[0-9]//g' )
        if [ -z "$chknum" ]
                then
                     for(( i=1;i<="$num";i=i+1 ))
                 		do
								#添加用户
   								/usr/sbin/useradd $name$i
#添加用户密码,passwd 的--stdin 参数是非交互输入,直接传入密码,不需要第二次确认
               echo $pass | /usr/bin/passwd --stdin $name$i
               echo "add $i"
               done
        else
                echo "the num must be number"
        fi
else
        echo "must be input name pass num"
fi

赋予脚本执行权限:chmod 755 脚本名称

while 循环和 until 循环

while 循环

while 循环是不定循环,也称条件循环。只要条件判断式成立,循环就会一直继续,直到条件判断式不成立,循环才会停止。这就和 for 的固定循环不太一样了。

#格式:
while[ 条件判断式]
      do
      	  程序
      done
#!/bin/bash
#从 1 加到 100
sum=0
i=1
#如果变量 i 的值小于等于 100,则执行循环
while [ $i -le 100 ]
        do
            sum=$(( $sum+$i ))
            i=$(( $i+1 ))
        done
echo "sum is : $sum"

until 循环

until 循环和 while 循环相反,until 循环时只要条件判断式不成立则进行循环,并执行循环程序。一旦循环条件成立,则终止循环。

格式:
until [ 条件判断式 ]
   do 
       程序
   done
#until 循环实例
#!/bin/bash
#until 循环 1 加到 100
sum=0
i=1
#循环直到变量 i 的值大于 100,就停止循环
until [ $i -gt 100 ]
        do
            sum=$(( $sum+$i ))
            i=$(( $i+1 ))
        done
echo "The sum is: $sum"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

上一篇:

下一篇: 没有了

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

情栀口红

暂无简介

0 文章
0 评论
469 人气
更多

推荐作者

已经忘了多久

文章 0 评论 0

15867725375

文章 0 评论 0

LonelySnow

文章 0 评论 0

走过海棠暮

文章 0 评论 0

轻许诺言

文章 0 评论 0

信馬由缰

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文