day029-Shell自动化编程-计算与while循环

发布于:2025-06-08 ⋅ 阅读:(18) ⋅ 点赞:(0)

1. read 交互式初始化变量

  • read是从标准输入获取数据,一般用来在脚本中交互式为变量赋值
  • -p “信息”:打印提示信息
  • -t:设置输入时间
  • -s:静默模式,不显示输入的数据,类似于输入密码

1.1 案例-安装不同的软件

[root@oldboy99-Kylin /server/scripts]# cat read_install_pkg.sh
#!/bin/bash
##############################################################
# File Name: read_install_pkg.sh
# Version: V1.0
# Author: SunKexu
# Organization: www.oldboyedu.com
# Description:
##############################################################

export LANG=en_US.UTF-8
cat <<EOF
请选择:
1.安装nginx
2.安装php
3.安装mysql
4.安装DeepSeek
5.安装tomcat
6.安装所有
7.退出
EOF
# read
read -p "请输入您的选择:" choose

# vars


# command
case $choose in
	1)echo install nginx ;;
	2)echo install php ;;
	3)echo install mysql ;;
	4)echo install DeepSeek ;;
	5)echo install tomcat ;;
	6)echo install all ;;
	7) exit ;;
	*)
		echo "Usage:$0 数字"
		exit 1
esac


[root@oldboy99-Kylin /server/scripts]# bash read_install_pkg.sh
请选择:
1.安装nginx
2.安装php
3.安装mysql
4.安装DeepSeek
5.安装tomcat
6.安装所有
7.退出
请输入您的选择:100
Usage:read_install_pkg.sh 数字
[root@oldboy99-Kylin /server/scripts]# bash read_install_pkg.sh
请选择:
1.安装nginx
2.安装php
3.安装mysql
4.安装DeepSeek
5.安装tomcat
6.安装所有
7.退出
请输入您的选择:1
install nginx
[root@oldboy99-Kylin /server/scripts]# bash read_install_pkg.sh
请选择:
1.安装nginx
2.安装php
3.安装mysql
4.安装DeepSeek
5.安装tomcat
6.安装所有
7.退出
请输入您的选择:6
install all
[root@oldboy99-Kylin /server/scripts]# bash read_install_pkg.sh
请选择:
1.安装nginx
2.安装php
3.安装mysql
4.安装DeepSeek
5.安装tomcat
6.安装所有
7.退出
请输入您的选择:7

1.2 案例-比较大小

[root@oldboy99-Kylin /server/scripts]# cat compare_2.sh
#!/bin/bash
##############################################################
# File Name: compare_2.sh
# Version: V1.0
# Author: SunKexu
# Organization: www.oldboyedu.com
# Description:比较大小,交互传参
##############################################################
export LANG=en_US.UTF-8

# vars
read -p "请输入参数1、参数2:" num1 num2


# command
# 判断是否是数字
if [[ ! "$num1" =~ ^-?[0-9]+$ || ! "$num2" =~ ^-?[0-9]+$ ]];then
	echo "$num1或者${num2}不是数字"
	exit 1
fi
#[[ "$num2" =~ ^-?[0-9]+$ ]] || {
#	echo "$num2 不是数字"
#	exit 1
#}
# 比较
if [ $num1 -gt $num2 ];then
	echo "$num1 > $num2"
elif [ $num1 -eq $num2 ];then
	echo "$num1 = $num2"
else
	echo "$num2 > $num1"
fi


[root@oldboy99-Kylin /server/scripts]# bash compare_2.sh 
请输入参数1、参数2:-3 a         
-3或者a不是数字
[root@oldboy99-Kylin /server/scripts]# bash compare_2.sh 
请输入参数1、参数2:-1 -3
-1 > -3
[root@oldboy99-Kylin /server/scripts]# bash compare_2.sh 
请输入参数1、参数2:30 23
30 > 23
[root@oldboy99-Kylin /server/scripts]# bash compare_2.sh 
请输入参数1、参数2:10 20  
20 > 10

2. 计算

计算方案 说明 应用场景
awk/bc 整数、小数都可以计算 计算小数、整数,或比较大小
expr 计算整数 检查输入的内容是否为数字(也可以用[[ =~ ]])
let/$(())/$[] 计算整数 配合循环使用

2.1 bc

bc:Basic calculation,基础计算

  • -l(小写的L):使用标准数学库,显示精准小数
  • 直接使用是交互式的计算器
  • 非交互式一般和echo配合使用
# 计算器
[root@oldboy99-Kylin /server/scripts]# bc
bc 1.07.1
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
22-10
12
10^3
1000
……
[root@oldboy99-Kylin /server/scripts]# echo "10+20" |bc
30
[root@oldboy99-Kylin /server/scripts]# echo "10-20" |bc
-10
[root@oldboy99-Kylin /server/scripts]# echo "10*20" |bc
200
[root@oldboy99-Kylin /server/scripts]# echo "10/20" |bc
0
[root@oldboy99-Kylin /server/scripts]# echo "10/20" |bc -l
.50000000000000000000
[root@oldboy99-Kylin /server/scripts]# echo "10^2" |bc 
100
[root@oldboy99-Kylin /server/scripts]# echo "10%2" |bc 
0

2.2 awk

  • -v <变量名>=<值>: 设置 awk 内部的变量值。可以使用该选项将外部值传递给 awk 脚本中的变量。
  • BEGIN关键词:BEGIN{},里面存放awk执行前的语句
[root@oldboy99-Kylin /server/scripts]# awk -v n1=10 'BEGIN{print n1}'
10
[root@oldboy99-Kylin /server/scripts]# awk -v n1=10 'BEGIN{print n1}'
10
[root@oldboy99-Kylin /server/scripts]# awk -v n1=10 -v n2=20 'BEGIN{print n1+n2}'
30
[root@oldboy99-Kylin /server/scripts]# awk -v n1=10 -v n2=20 'BEGIN{print n1-n2}'
-10
[root@oldboy99-Kylin /server/scripts]# awk -v n1=10 -v n2=20 'BEGIN{print n1*n2}'
200
[root@oldboy99-Kylin /server/scripts]# awk -v n1=10 -v n2=20 'BEGIN{print n1/n2}'
0.5
[root@oldboy99-Kylin /server/scripts]# awk -v n1=10 -v n2=20 'BEGIN{print n1^n2}'
100000000000000000000
[root@oldboy99-Kylin /server/scripts]# awk -v n1=10 -v n2=20 'BEGIN{print n1%n2}'
10
[root@oldboy99-Kylin /server/scripts]# awk -v n1=10 -v n2=20 'BEGIN{print n2%n1}'
0
# 集合变量计算
[root@oldboy99-Kylin /server/scripts]# num1=10
[root@oldboy99-Kylin /server/scripts]# num2=20
[root@oldboy99-Kylin /server/scripts]# awk -v n1=$num1 -v n2=$num2 'BEGIN{print n1}'
10
[root@oldboy99-Kylin /server/scripts]# awk -v n1=$num1 -v n2=$num2 'BEGIN{print n1+n2}'
30
[root@oldboy99-Kylin /server/scripts]# awk -v n1=$num1 -v n2=$num2 'BEGIN{print n1-n2}'
-10
[root@oldboy99-Kylin /server/scripts]# awk -v n1=$num1 -v n2=$num2 'BEGIN{print n1*n2}'
200
[root@oldboy99-Kylin /server/scripts]# awk -v n1=$num1 -v n2=$num2 'BEGIN{print n1/n2}'
0.5
[root@oldboy99-Kylin /server/scripts]# awk -v n1=$num1 -v n2=$num2 'BEGIN{print n2^n1}'
10240000000000
[root@oldboy99-Kylin /server/scripts]# awk -v n1=$num1 -v n2=$num2 'BEGIN{print n2%n1}'
0
[root@oldboy99-Kylin /server/scripts]# awk -v n1=$num1 -v n2=$num2 'BEGIN{print n1%n2}'
10

2.3 expr

expr:evaluate expressions,计算表达式

  • 一般用来验证变量是否是数字
  • 也能计算字符串长度
# 数字与算数字符之间要有空格
[root@oldboy99-Kylin /server/scripts]# expr 10 + 20
30
[root@oldboy99-Kylin /server/scripts]# expr 10 - 20
-10
[root@oldboy99-Kylin /server/scripts]# expr 10 * 20
expr: 语法错误:未预期的参数 “api.txt”
# 要用转义字符
[root@oldboy99-Kylin /server/scripts]# expr 10 \* 20
200
# expr只能计算整数,结果也只能是整数
[root@oldboy99-Kylin /server/scripts]# expr 10 / 20
0
# 判断变量是否是数字
[root@oldboy99-Kylin /server/scripts]# num=10
[root@oldboy99-Kylin /server/scripts]# expr $num + 1
11
[root@oldboy99-Kylin /server/scripts]# echo $?
0
[root@oldboy99-Kylin /server/scripts]# name=skx
[root@oldboy99-Kylin /server/scripts]# expr $name + 1
expr: 非整数参数
[root@oldboy99-Kylin /server/scripts]# echo $?
2
# 计算字符串长度
[root@oldboy99-Kylin /server/scripts]# expr length skx123oldboy
12
[root@oldboy99-Kylin /server/scripts]# expr length $name
3
# 变量扩展符也能显示字符长度
[root@oldboy99-Kylin /server/scripts]# echo ${#name}
3

2.4 let

let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。

  • let的结果必须用变量来接收,并直接修改原变量内容
  • let的结果只能是整数
[root@oldboy99-Kylin /server/scripts]# echo $n
10
[root@oldboy99-Kylin /server/scripts]# let n=10+2
[root@oldboy99-Kylin /server/scripts]# echo $n
12
[root@oldboy99-Kylin /server/scripts]# let n=10-2
[root@oldboy99-Kylin /server/scripts]# echo $n
8
[root@oldboy99-Kylin /server/scripts]# let n=10*2
[root@oldboy99-Kylin /server/scripts]# echo $n
20
[root@oldboy99-Kylin /server/scripts]# let n=10/2
[root@oldboy99-Kylin /server/scripts]# echo $n
5
[root@oldboy99-Kylin /server/scripts]# let n=10^2
[root@oldboy99-Kylin /server/scripts]# echo $n
8
[root@oldboy99-Kylin /server/scripts]# let n=10%2
[root@oldboy99-Kylin /server/scripts]# echo $n
0
[root@oldboy99-Kylin /server/scripts]# let n=10/3
[root@oldboy99-Kylin /server/scripts]# echo $n
3
# 使用let自增或自减
[root@oldboy99-Kylin /server/scripts]# let n++
[root@oldboy99-Kylin /server/scripts]# echo $n
4
[root@oldboy99-Kylin /server/scripts]# let n--
[root@oldboy99-Kylin /server/scripts]# echo $n
3

2.5 案例-计算内存的空闲率

  • 注意单位
[root@oldboy99-Kylin /server/scripts]# free -k |awk 'NR==2{print $NF/$2*100"%"}'
55.9613%
[root@oldboy99-Kylin /server/scripts]# free -m |awk 'NR==2{print $NF/$2*100"%"}'
55.8017%

2.6 案例-检查域名过期时间和https整数过期时间

  • 检查域名过期时间:whois 二级域名,关键词:Expiration Date
  • 检查https证书过期时间:curl -v https://www.二级域名,关键词:expire date
  • -v:显示请求与响应的详细信息
  • date
  • -d " ":读取字符串时间
  • +%s:获取时间戳
[root@oldboy99-Kylin /server/scripts]# cat check_domain_https_expire.sh
#!/bin/bash
##############################################################
# File Name: check_domain_https_expire.sh
# Version: V1.0
# Author: SunKexu
# Organization: www.oldboyedu.com
# Description:检查域名和https证书过期时间
##############################################################
export LANG=en_US.UTF-8
# vars
time_stamp=`date +%s`


# command
while true
do
# 用户需要输入一个二级域名
	read -p "请输入一个二级域名:" domain
# 检查用户输入的域名
	[[ $domain =~ ^[^\ ]+\.[a-z]+$ ]] || {
		echo "输入的二级域名有误,请重新输入"
		continue
	}
# 检查域名过期时间
	expire_domain=`date -d $(whois ${domain} |awk -F ': ' '/Expiration Date/{print $2}') +%s`
# 检查https证书过期时间
	expire_https=`date -d "$(curl -v https://www.${domain} |& awk -F ': ' '/expire date/{print $2}')" +%s`
# 计算相差时间
	days_domain=`echo "(${expire_domain}-${time_stamp})/60/60/24" |bc`
	days_https=`echo "(${expire_https}-${time_stamp})/60/60/24" |bc`
cat <<EOF
	${domain}:
	域名还有${days_domain}天过期"
	https证书还有${days_https}天过期"
EOF
	exit 
done
[root@oldboy99-Kylin /server/scripts]# bash check_domain_https_expire.sh
请输入一个二级域名:baidu 123.com  
输入的二级域名有误,请重新输入
请输入一个二级域名:baidu.com
	baidu.com:
	域名还有1222天过期"
	https证书还有62天过期"

3. 循环

3.1 循环控制语句

循环控制 说明
exit 退出脚本
continue 跳过本次循环,进入下一次循环
break 打断,结束循环
return 函数返回值

3.2 for循环-c语言格式

[root@oldboy99-Kylin /server/scripts]# cat test.sh
#!/bin/bash
##############################################################
# File Name: test.sh
# Version: V1.0
# Author: SunKexu
# Organization: www.oldboyedu.com
# Description:
##############################################################
for(( i=1;i<=10;i++))
do
	echo $i
done
[root@oldboy99-Kylin /server/scripts]# bash test.sh
1
2
3
4
5
6
7
8
9
10

3.3 while循环

3.3.1 案例-猜数字

  • 生成随机数:$RANDOM,随机数范围:0-32767
  • 32767是16位二进制无符号整数,数值位全为1

在这里插入图片描述

  • 生成1-100之间的随机数:$RANDOM%100+1
[root@aliyun-ubuntu /server/scripts]# cat GuessNumber.sh
#!/bin/bash
##############################################################
# File Name: GuessNumber.sh
# Version: V1.0
# Author: SunKexu
# Organization: www.oldboyedu.com
# Description:Guess the numbers
##############################################################
export LANG=en_US.UTF-8


# vars
# random num
num=$(($RANDOM%100+1))

# command
while true
do
	read -p "Please enter the number you guessed (1-100):" user
	# check user para
	[[ $user =~ ^[0-9]+$ ]] || {
		echo "Please enter a number (1-100):"
		continue
	}
	if [ $user -eq $num ];then
		echo "Congratulations, you guessed right"
		exit
	elif [ $user -gt $num ];then
		echo "Guess too big"
	else
		echo "Guess too small"
	fi
done

[root@aliyun-ubuntu /server/scripts]# bash GuessNumber.sh
Please enter the number you guessed (1-100):50
Guess too small
Please enter the number you guessed (1-100):60
Guess too small
Please enter the number you guessed (1-100):70
Guess too small
Please enter the number you guessed (1-100):80
Guess too big
Please enter the number you guessed (1-100):75
Guess too big
Please enter the number you guessed (1-100):74
Guess too big
Please enter the number you guessed (1-100):73
Guess too big
Please enter the number you guessed (1-100):72
Congratulations, you guessed right

3.3.2 读取文件

  • while读取文件时是按行读取的
[root@aliyun-ubuntu /server/scripts]# cat read_file.sh 
#!/bin/bash
##############################################################
# File Name: read_file.sh
# Version: V1.0
# Author: SunKexu
# Organization: www.oldboyedu.com
# Description:
##############################################################
export LANG=en_US.UTF-8

# vars
file=$1
# check para
[ $# -eq 0 ] && {
	echo "Usage:$0 filename"
	exit 1
}
while read line
do
	echo $line
done < $file
[root@aliyun-ubuntu /server/scripts]# bash read_file.sh /etc/passwd |head
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin

3.3.3 案例-读取文件,批量ping和wget

  • ping -W 数字:每次请求的超时时间,单位秒
  • wget:
  • -S/–spider:不下载任何文件
  • -T 数字:设置连接请求的超时时间,单位秒
  • -t 数字:设置重试次数
[root@oldboy99-Kylin /server/scripts]# cat check_ping_wget.sh 
#!/bin/bash
##############################################################
# File Name: check_ping_wget.sh
# Version: V1.0
# Author: SunKexu
# Organization: www.oldboyedu.com
# Description:读取文件,批量ping和wget
##############################################################
export LANG=en_US.UTF-8

# vars
file=$1

# command
[ $# -eq 0 ] && {
	echo "$0 filename(has ip/domain ……)"
	exit 1
}
while read line
do
	ping -c 2 -W 1 $line >/dev/null 2>&1
	[ $? -eq 0 ] && echo "$line 可以ping通" || echo "$line 不能ping通"
	wget -S -T 1 -t 1 $line >/dev/null 2>&1
	[ $? -eq 0 ] && echo "$line 可以访问" || echo "$line 不能访问"
	echo "-----------------------"
done < $1
[root@oldboy99-Kylin /server/scripts]# bash check_ping_wget.sh ./log/ip.txt 
10.0.0.200 可以ping通
10.0.0.200 不能访问
-----------------------
baidu.com 可以ping通
baidu.com 可以访问
-----------------------
jd.com 可以ping通
jd.com 可以访问
-----------------------
csdn.net 可以ping通
csdn.net 可以访问
-----------------------

4. 踩坑记录

1. -bash: 条件表达式中有语法错误

在这里插入图片描述

修改:

  • 空格:[:space:]

在这里插入图片描述

  • 或者将空格转义

在这里插入图片描述

5. 思维导图

【金山文档 | WPS云文档】 思维导图 https://kdocs.cn/l/co3I7PtpTYQX