数值运算与if条件判断
数值运算&&if条件判断
[TOC]
📦 变量子串
长度统计
统计字符串的长度(笔试题)
三种统计字符串长度的方法:
1)wc -L'-L vs -l:小写 -l 是行数,大写 -L 是最长行长度'[root@shell ~]# name=oldboy[root@shell ~]# echo $nameoldboy[root@shell ~]# echo $name | wc -L6
2)awk length[root@shell ~]# echo $name | awk '{print length}'6
3)子串统计长度 — ${#变量名} ✅ 最常用[root@shell ~]# echo ${#name}6📌 ${#变量名} 是 bash 内置语法,==效率最高==,推荐使用
统计长度小于 3 的字符串
1)for 循环 + ${#i}[root@shell ~]# cat for.sh#!/bin/bashfor i in I am lizhenya I am 18# 不能加引号,不然会变成一个整体do echo $idone[root@shell ~]# sh for.shIamlizhenyaIam18
2)输出每个字符的长度 & 并比较# 只输出长度小于 3 的字符串[root@shell ~]# cat for.sh#!/bin/bashfor i in I am lizhenya I am 18do [ ${#i} -lt 3 ] && echo $idone[root@shell ~]# sh for.shIamIam18扩展 — 用三剑客实现同样的效果:
1)xargs + awk[root@shell ~]# echo I am lizhenya I am 18 | xargs -n1IamlizhenyaIam18[root@shell ~]# echo I am lizhenya I am 18 | xargs -n1 | awk '{print length}'128122[root@shell ~]# echo I am lizhenya I am 18 | xargs -n1 | awk '{if(length<3) print}'IamIam18
2)纯 awk'NF --> 每行有多少列' # 默认以空格分开[root@shell ~]# echo I am lizhenya I am 18 | awk '{for(i=1;i<=NF;i++) if(length($i)<3) print $i}'✅ 给i一个初值,$i为每一列字符 ⚠️ 中间是分号IamIam18子串删除
从前往后删除
[root@shell ~]# url=www.baidu.com[root@shell ~]# echo $urlwww.baidu.com[root@shell ~]# echo ${#url}13⚠️ #号 在前面是统计字符串长度 ⚠️'依旧是{ 花括号 }'
1)# 匹配 — 删除最短匹配(从前往后)[root@shell ~]# echo ${url#www.}baidu.com# '删掉了开头的 www.'[root@shell ~]# echo ${url#w}ww.baidu.com'只删了第一个 w,# 是懒惰匹配(最短)'[root@shell ~]# echo ${url#*.}baidu.com# '匹配到第一个 . 就停,删掉 www.'[root@shell ~]# echo ${url#*.*.}com# 'w*.*. 匹配到第二个点,删掉 www.baidu.'
2)## 匹配 — 删除最长匹配(从前往后,贪婪)[root@shell ~]# echo ${url##*.}com'贪婪匹配到最后一个点,只留下 com'| 语法 | 方向 | 匹配方式 | 记忆技巧 |
|---|---|---|---|
# | 从前往后 | ==最短匹配==(懒惰) | 键盘上 # 在左,管左边 |
## | 从前往后 | ==最长匹配==(贪婪) | 两个 # 就贪到底 |
% | 从后往前 | ==最短匹配==(懒惰) | 键盘上 % 在右,管右边 |
%% | 从后往前 | ==最长匹配==(贪婪) | 两个 % 就贪到底 |
从后往前删除
[root@shell ~]# echo ${url}www.baidu.com
1)% 匹配 — 从后往前删除最短匹配[root@shell ~]# echo ${url%com}www.baidu.[root@shell ~]# echo ${url%.com}www.baidu[root@shell ~]# echo ${url%.*}www.baidu# '匹配到最后一个 . 前面的全部留下'
2)%% 匹配 — 从后往前删除最长匹配[root@shell ~]# echo ${url%%.*}www# '贪婪从后往前,匹配到第一个 . 就全删了'实战案例 — 去掉磁盘容量的单位 G:
[root@shell ~]# df -h | awk 'NR==6'/dev/sda3 48G 4.9G 43G 11% /[root@shell ~]# df -h | awk 'NR==6{print $2}'48G[root@shell ~]# disk=`df -h | awk 'NR==6{print $2}'`[root@shell ~]# echo $disk48G
'${disk%G} — 从后面把 G 删掉,拿到纯数字'[root@shell ~]# echo ${disk%G}48[root@shell ~]# [ ${disk%G} -gt 30 ]-gt > '大于'[root@shell ~]# echo $?0# '48 > 30,成立'
# 纯 awk[root@shell ~]# df -h | awk -F '[ G]+' '{print $(NF-4)}'48子串替换
[root@shell ~]# url=www.baidu.com
1)/ 替换 — 只替换第一个匹配[root@shell ~]# echo ${url/w/W}Www.baidu.com✅ 单个 `/` → 替换一次就停止✅ 双 `//` → 全局替换
[root@shell ~]# echo ${url/wW/W}www.baidu.com# 'wW 这个模式不存在,所以没替换'
[root@shell ~]# echo ${url/ww/W}Ww.baidu.com# '只替换了第一个 ww'
2)// 替换 — 替换所有匹配(全局替换)[root@shell ~]# echo ${url//w/W}WWW.baidu.com# '所有的 w 都变成了 W'
3)替换域名 '百度' --> '京东'[root@shell ~]# echo ${url/baidu/jd}www.jd.com| 语法 | 含义 |
|---|---|
${变量/旧/新} | 替换第一个匹配 |
${变量//旧/新} | 替换所有匹配 |
${变量/#旧/新} | 匹配开头(必须是前缀)才替换 |
${变量/%旧/新} | 匹配结尾(必须是后缀)才替换 |
url="www.baidu.www.com"
# 1️⃣ 普通替换:只换第一个 wecho ${url/w/W} # Www.baidu.www.com
# 2️⃣ 全局替换:所有 w 都换echo ${url//w/W} # WWW.baidu.WWW.com
# 3️⃣ # 锚定开头:只有开头的 www 被替换echo ${url/#www/W} # W.baidu.www.com
# 4️⃣ % 锚定结尾:只有结尾的 com 被替换echo ${url/%com/COM} # www.baidu.www.COM
# ❌ # 不匹配开头时:什么都不发生echo ${url/#baidu/BAIDU} # www.baidu.www.com(baidu不在开头,原样输出)⚙️ 数值运算
Shell 中常见的 6 种运算方式:
| 方式 | 整数 | 小数 | 效率 | 推荐度 |
|---|---|---|---|---|
expr | ✅ | ❌ | 低(需 fork 子进程) | ⭐⭐ |
$(()) | ✅ | ❌ | ==最高==(bash 内置) | ⭐⭐⭐⭐⭐ |
$[] | ✅ | ❌ | 高(bash 内置) | ⭐⭐⭐ |
let | ✅ | ❌ | 高(bash 内置) | ⭐⭐⭐ |
bc | ✅ | ✅ | 低(需 fork 子进程) | ⭐⭐⭐ |
awk | ✅ | ✅ | 低(需 fork 子进程) | ⭐⭐⭐ |
expr — 支持整数、不支持小数
'expr 要求运算符两边必须有空格!'[root@shell ~]# expr 1+11+1# ❌ 没空格,当成字符串原样输出[root@shell ~]# expr 1 + 12
'乘法需要用 \* 转义'[root@shell ~]# expr 100 \* 101000[root@shell ~]# expr 100 / 1010[root@shell ~]# expr 100 - 1090$(()) — 支持整数、效率最高
'两个小括号' ✅ 推荐使用[root@shell ~]# echo $((10+10))20[root@shell ~]# echo $((10-10))0[root@shell ~]# echo $((10*10))100[root@shell ~]# echo $((10/10))1[root@shell ~]# echo $((10%10))0# '% 是取余(取模)'$[] — 不支持小数(老式语法)
[root@shell ~]# echo $[10+10]20[root@shell ~]# echo $[10-10]0[root@shell ~]# echo $[10*10]100[root@shell ~]# echo $[10/10]1'$[] 是老式写法,推荐用 $(()) 替代'let — 常用于自增/自减
Shell(Bash)在进行算术运算时(包括 let、(( ))、expr),如果变量未被赋值或值为空,会自动将其当作 整数 0 处理
1)let i++ —-> 自增[root@shell ~]# let i++[root@shell ~]# echo $i1[root@shell ~]# let i++[root@shell ~]# echo $i2
2)let i=i+1[root@shell ~]# let i=i+1[root@shell ~]# echo $i3📌 i++ 和 ++i 的区别(有变量时不同):
[root@shell ~]# a=1[root@shell ~]# b=1[root@shell ~]# let c=a++ # 先赋值后运算[root@shell ~]# let d=++b # 先运算后赋值[root@shell ~]# echo $c1[root@shell ~]# echo $d2a++→ 先把a的值给c,然后a自增++b→ 先让b自增,再把结果给d
实战 — 用 let 统计循环次数:
[root@shell ~]# cat for.sh#!/bin/bashfor i in I am lizhenya I am 18do let a++doneecho 总共循环了 $a 次[root@shell ~]# sh for.sh总共循环了 6 次bc — 支持整数和小数
[root@shell ~]# echo 10+10 | bc20[root@shell ~]# echo 10-10 | bc0[root@shell ~]# echo 10*10 | bc100[root@shell ~]# echo 10/10 | bc1
'bc 独有的优势:支持小数运算'[root@shell ~]# echo 10+10.5 | bc20.5[root@shell ~]# echo 10.123+10.5 | bc20.623
'小数除法'[root@shell ~]# echo 10/3 | bc3[root@shell ~]# echo 10/2.5 | bc4[root@shell ~]# echo 10/2.3 | bc4# '默认不保留小数位'
'支持运算优先级'[root@shell ~]# echo 10+2*2 | bc14awk BEGIN — 支持整数和小数
[root@shell ~]# awk 'BEGIN{print 10*10}'100[root@shell ~]# awk 'BEGIN{print 10-10}'0[root@shell ~]# awk 'BEGIN{print 10/10}'1[root@shell ~]# awk 'BEGIN{print 10+10}'20[root@shell ~]# awk 'BEGIN{print 10+10*2}'30[root@shell ~]# awk 'BEGIN{print 10^22}'10000000000000000000000
'awk 小数除法默认保留精度'[root@shell ~]# awk 'BEGIN{print 10/3}'3.33333💡 选择建议:
- 整数运算 →
$(())效率最高,bash 内置 - 小数运算 →
bc或awk - 自增/统计 →
let - ==运算中都支持变量==:
$(($num1 * $num2))、$[$num1 * $num2]、expr $num1 + $num2
⚙️ 整数比较
语法结构
# 第一种: testtest 10 -eq 10
# 第二种: [ ] ✅ 最常用[ 10 -eq 10 ]✨比较符号
| 运算符 | 含义 | 英文全称 | 助记 |
|---|---|---|---|
-lt | 小于 | Less Than | Less Than |
-gt | 大于 | Greater Than | Greater Than |
-le | 小于等于 | Less or Equal | ≤ |
-ge | 大于等于 | Greater or Equal | ≥ |
-eq | 等于 | Equal | = |
-ne | 不等于 | Not Equal | ≠ |
'基础演示'[root@shell ~]# test 10 -eq 10[root@shell ~]# echo $?0[root@shell ~]# [ 10 -eq 10 ][root@shell ~]# echo $?0
'搭配 && 和 ||'[root@shell ~]# [ 10 -gt 5 ] && echo 成立 || echo 不成立成立[root@shell ~]# [ 10 -eq 5 ] && echo 成立 || echo 不成立不成立[root@shell ~]# [ 10 -lt 5 ] && echo 成立 || echo 不成立不成立[root@shell ~]# [ 10 -lt 10 ] && echo 成立 || echo 不成立不成立⚠️ '小于,不包含等于'[root@shell ~]# [ 10 -ge 10 ] && echo 成立 || echo 不成立成立 '≥'[root@shell ~]# [ 10 -le 10 ] && echo 成立 || echo 不成立成立 '≤'支持变量
[root@shell ~]# echo $num110[root@shell ~]# echo $num210
[root@shell ~]# [ $num1 -eq $num2 ] && echo 成立 || echo 不成立成立支持命令
[root@Rocky ~]# df -h | awk '/\/$/''先过滤出以根/结尾的行' --> 撬棍/dev/mapper/rlm-root 16G 1.7G 15G 11% /[root@shell ~]# df -h | awk -F "[ %]+" '/\/$/{print $(NF-1)}'11'获取根分区使用率(去掉 % 号)'[root@shell ~]# [ `df -h | awk -F "[ %]+" '/\/$/{print $(NF-1)}'` -gt 10 ] && echo 成立 || echo 不成立成立
'使用变量方式做比较 — 更清晰'[root@shell ~]# disk=`df -h | awk -F "[ %]+" '/\/$/{print $(NF-1)}'`[root@shell ~]# echo $disk11[root@shell ~]# [ $disk -gt 80 ] && echo 成立 || echo 不成立不成立灵活取值 — 子串删除配合整数比较
'不加 awk -F 过滤,拿到的是 11% 带百分号'[root@shell ~]# disk=`df -h | awk '/\/$/{print $(NF-1)}'`[root@shell ~]# echo $disk11%[root@shell ~]# [ $disk -gt 10 ] && echo 成立 || echo 不成立-bash: [: 11%: integer expression expected不成立# ❌ '带 % 不能直接做整数比较!'
'用 ${disk%\%} 去掉百分号'[root@shell ~]# [ ${disk%\%} -gt 10 ] && echo 成立 || echo 不成立成立💡 ${disk%\%} — 用 \ 转义 %,表示从后面删除一个 % 字符
也可以用 ${disk%?} 删掉最后一个字符
[root@shell ~]# disk=$(df -h | awk '/\/$/{print $(NF-1)}')[root@shell ~]# echo $disk11%[root@shell ~]# echo ${disk%?}11多整数比较 — -o 和 -a
⚠️
-o/-a是过时语法,现代 Shell 脚本中不推荐使用请用
||/&&和[[ ]]替代 ✅
| 含义 | ❌ 旧写法(-o/-a) | ✅ 推荐写法([[ ]]) |
|---|---|---|
| OR | [ A -o B ] | `[[ A |
| AND | [ A -a B ] | [[ A && B ]] |
| 混合 | [ A -a B -o C ] | `[[ A && B |
实战案例
🌰 案例 1 — 磁盘使用率告警
脚本逻辑流程:
① 取主机名、IP、磁盘使用率 → ② 用 ${disk_use%\%} 去掉百分号 → ③ 整数比较判断 → ④ 大于阈值发告警,小于发正常通知
[root@shell ~]# cat disk.sh#!/bin/bash
# 取值定义变量HOST=`hostname`IP=`hostname -I | awk '{print $1}'`disk_use=`df -h | awk '/\/$/{print $(NF-1)}'`
# 比对判断if [ ${disk_use%\%} -gt 10 ]then python3 weixin.py "ShiHao" "${IP}_$HOST: 磁盘告警" "当前磁盘使用率为$disk_use,请快速处理!"else python3 weixin.py "ShiHao" "${IP}_$HOST: 磁盘正常" "当前磁盘使用率为$disk_use,喝喝茶吧"fi🌰 案例 2 — 内存使用率超过 80% 告警
[root@shell ~]# free | awk 'NR==2{print $3/$2*100}'20.3711[root@shell ~]# t=`free | awk 'NR==2{print $3/$2*100}'`[root@shell ~]# [ ${t%.*} -eq 20 ] && echo 成立成立📌 ${t%.*} — 从后面删除 . 及之后的内容,拿到整数部分
🌰 案例 3 — 负载平均值大于 1 则告警
[root@shell ~]# uptime 11:23:35 up 9:29, 2 users, load average: 0.18, 0.11, 0.09num1=$(uptime | awk -F'[ ,]+' '{print $NF}')num2=$(uptime | awk -F'[ ,]+' '{print $(NF-1)}')nmu3=$(uptime | awk -F'[ ,]+' '{print $(NF-2)}')
⚠️ '只有bc 和 awk命令支持小数' --> 可以都乘100再比较📦 文件判断
语法结构与判断符号
# 语法结构test -f /etc/hosts[ -f /etc/hosts ]| 符号 | 含义 | 说明 |
|---|---|---|
-f | ==普通文件==存在则为真 | -f /etc/hosts |
-d | ==目录==存在则为真 | -d /etc/ |
-e | ==存在==则为真(文件和目录都行) | -e /etc/passwd |
-r | ==可读==则为真 | -r /etc/hosts |
-w | ==可写==则为真 | -w /etc/hosts |
-x | ==可执行==则为真 | -x /etc/hosts |
1)基础演示[root@shell ~]# [ -f /etc/hosts ] && echo 存在 || echo 不存在存在[root@shell ~]# [ -f /etc/ ] && echo 存在 || echo 不存在不存在# '/etc/ 是目录,不是普通文件'[root@shell ~]# [ -d /etc/ ] && echo 存在 || echo 不存在存在[root@shell ~]# [ -e /etc/ ] && echo 存在 || echo 不存在存在[root@shell ~]# [ -e /etc/passwd ] && echo 存在 || echo 不存在存在
2)权限判断[root@shell ~]# [ -r /etc/hosts ] && echo 存在 || echo 不存在存在[root@shell ~]# [ -w /etc/hosts ] && echo 存在 || echo 不存在存在[root@shell ~]# [ -x /etc/hosts ] && echo 存在 || echo 不存在不存在# '普通文件默认没有执行权限' --> 0644[root@shell ~]# [ -x /etc/ ] && echo 存在 || echo 不存在存在# '目录默认有执行权限(x 对目录意味着可以 cd 进去)' --> 755实战案例
🌰 案例 1 — 文件存在则 source 执行
[root@shell ~]# unset name[root@shell ~]# cat a.shname=gege[root@shell ~]# echo $name'🈳'[root@shell ~]# cat test.sh#!/bin/bash[ -f /root/a.sh ] && . /root/a.shecho $name
[root@shell ~]# bash test.shgege# 'a.sh 存在,source 执行后 $name 被导入当前脚本'🌰 案例 2 — .bashrc 中的 -f 判断
[root@shell ~]# cat ~/.bashrc# Source global definitionsif [ -f /etc/bashrc ]; then # 如果 /etc/bashrc 存在则调用执行 . /etc/bashrcfi
# User specific aliases and functionsalias rm='rm -i'alias cp='cp -i'alias mv='mv -i'📌 这就是之前讲过的:~/.bashrc 里主动 source /etc/bashrc
🌰 案例 3 — 目录不存在则创建
[root@shell ~]# [ -d oldboy ] || mkdir oldboy# 'oldboy 目录不存在 → 创建'🌰 案例 4 — 支持 -o 和 -a
[root@shell ~]# [ -f /etc/hosts -o -d hehe ] && echo 成立 || echo 不成立成立# '/etc/hosts 存在,-o 只要一个成立即可'✅ 比起上面的方法,我更推荐下面这种方法[root@shell ~]# [[ -f /etc/hosts || -d hehe ]] && echo 成立 || echo 不成立成立
[root@shell ~]# [[ -f /etc/hosts && -d hehe ]] && echo 成立 || echo 不成立不成立# '/etc/hosts 存在但 hehe 目录不存在,&& 要求全部成立'🔣 字符串判断
语法结构
test a = a[ a = a ][ a != b ]判断符号
| 符号 | 含义 |
|---|---|
= | 字符串相等 |
!= | 字符串不相等 |
-n | 字符串长度==不为 0==则成立 ==n==ot empty(非空则为真) |
-z | 字符串长度==为 0==则成立 ==z==ero length(长度为 0 则为真) |
✅ -n 和 -z 是相反的
-n和-z直接判断变量本身的值即可- 不需要使用
${#name}
- 不需要使用
1)字符串相等/不相等[root@shell ~]# [ root = root ] && echo 相等 || echo 不等于相等[root@shell ~]# [ aroot = root ] && echo 相等 || echo 不等于不等于
2)判断字符串长度 -n 和 -z[root@shell ~]# num=123[root@shell ~]# [ -n $num ] && echo 成立 || echo 不成立成立# '-n 长度不为 0 → 成立'[root@shell ~]# [ -z $num ] && echo 成立 || echo 不成立不成立# '-z 长度为 0 → 不成立'⚠️ 重要提醒:务必加双引号
3)错误示范[root@shell ~]# num=[root@shell ~]# [ -n $num ] && echo 成立 || echo 不成立成立 '我给了一个空,应该是不成立的 ❌'[ -n $num ] → shell 展开为 [ -n ] → 永远成立(bug!)[ -n "$num" ] → shell 展开为 [ -n "" ] → 正确判断空字符串 → 返回假 ✅[root@shell ~]# [ -n "$num" ] && echo 成立 || echo 不成立不成立# 一定加引号[root@shell ~]# [ -z "$num" ] && echo 成立 || echo 不成立成立# 长度为 0 → -z 成立'唯一不需要加引号的场景是纯数字算术比较且你确定变量==一定是合法整数==
- 但即便如此,加引号也不会有任何副作用
💡 终极建议:不要记”哪个可以省引号”,养成无条件加双引号的肌肉记忆 ✅
# ✅ 永远这样写[ -n "$var" ][ -z "$var" ][ "$a" = "$b" ][ "$count" -gt 0 ]实战案例
🌰 案例 1 — 字符串比对(登录验证)
[root@shell ~]# cat name.sh#!/bin/bashecho -e "web01 web01@123.com\nweb02 web02@123.com\njiu jiu@123.com" > ./a.txtread -p "请输入你的用户名: " namenum=`grep -w $name a.txt | wc -l`# -w精确匹配 0/1[ "$num" -ne 1 ] && echo 用户名错误请重新输入 && exit
read -s -p "请输入你的密码: " passwdecho -e "\n"[ "$passwd" != `grep -w $name a.txt | awk '{print $2}'` ] && echo 密码错误重新输入 && exitecho 恭喜你登录成功[root@shell ~]# cat ./a.txtweb01 web01@123.comweb02 web02@123.comjiu jiu@123.com🌰 案例 2 — 限制用户输入不能为空
[root@shell ~]# cat test.sh#!/bin/bashread -p "请输入你的姓名: " name[ -z "$name" ] && echo "必须输入姓名" && exit
read -p "请输入你的年龄: " age[ -z "$age" ] && echo "必须输入年龄" && exit
echo name=$nameecho age=$age⚙️ 正则判断
语法结构
[[ 字符串 =~ 正则表达式 ]]正则判断必须用 [[ ]] ==双中括号==,不能用 [ ] 单中括号
=~ 是正则匹配操作符
基础用法
'^ 匹配开头,$ 匹配结尾'[root@shell ~]# [[ root =~ ^r ]][root@shell ~]# echo $?0# '以 r 开头 → 匹配成功'
[root@shell ~]# [[ root =~ t$ ]][root@shell ~]# echo $?0# '以 t 结尾 → 匹配成功'
[root@shell ~]# [[ root =~ o ]][root@shell ~]# echo $?0# '包含字母 o → 匹配成功'⚠️ 不会自动加 ^(不强制开头匹配)
'包含判断'[root@shell ~]# [[ $USER =~ t$ ]] && echo 成立 || echo 不成立成立[root@shell ~]# [[ root =~ s ]] && echo 成立 || echo 不成立不成立正则模式
'[a-z] 匹配单个小写字母'[root@shell ~]# [[ root =~ [a-z] ]] && echo 成立 || echo 不成立成立
'^[a-z]+$ 匹配纯小写字母字符串'# + 连续出现(一次及以上)[root@shell ~]# [[ root =~ ^[a-z]+$ ]] && echo 成立 || echo 不成立成立[root@shell ~]# [[ 1root =~ ^[a-z]+$ ]] && echo 成立 || echo 不成立不成立# '1root、root1,中间有数字也不行'
'[a-Z] 匹配字母(含大小写)'[root@shell ~]# [[ Aroot =~ ^[a-Z]+$ ]] && echo 成立 || echo 不成立成立实战案例
- 通过正则匹配控制传入的参数
正则中使用 “并且” 和 “或者”
&& # 并且 — [[ ]] 内部使用|| # 或者 — [[ ]] 内部使用[root@shell ~]# cat test.sh#!/bin/bashread -p "请输入你的姓名: " nameif [[ ! "$name" =~ ^[a-z]+$ ]] # 如果姓名不是连续的字符串则表达式成立then # 成立则执行 then 后面的动作 echo "必须输入字符串" exitfi
read -p "请输入你的年龄: " ageif [[ ! "$age" =~ ^[0-9]+$ ]] # 如果年龄不是连续的数字则表达式成立then # 成立则执行 then 后面的动作 echo "必须输入整数" exitfi
echo name=$nameecho age=$age⚙️ if 条件判断
单分支(一个条件一个结果)
类似 [ 10 -eq 10 ] && echo 成立
if [ 条件表达式 ]then 命令集合fi
⚠️ 如果 then 写在 if 后面,'需要有;分号'if [ 条件表达式 ];then 命令集合fi分号与换行:];then 可以写在一行(中间必须有分号 ;)
也可以把 then 单独写在下一行(此时不需要分号)
1)单分支各种写法[root@shell ~]# cat if.sh#!/bin/bashif [ 10 -eq 10 ];then echo 成立fi
if [ 10 -eq 10 ]then echo 成立fi
if [ -f /etc/hosts ]then echo 成立fi
if [[ root =~ t$ ]]then echo 成立fi
if [ 10 -eq 10 -o -f /etc/hosts ];then# -o 单括号 echo 成立fi
if [[ 10 = 10 && etc =~ e ]];then# && 是双括号 echo 成立fi
[root@shell ~]# bash test.sh成立成立成立成立成立成立📌 if 后面可以是 ==任何条件判断==:
- 整数比较
[ 10 -eq 10 ] - 文件判断
[ -f /etc/hosts ] - 字符串判断
[ root = root ] - 正则判断
[[ root =~ t$ ]] - 多条件组合
[[ 10 = 10 && etc =~ e ]]
双分支(一个条件两个结果)
类似 [ 10 -eq 10 ] && echo 成立 || echo 不成立
if [ 条件表达式成立 ];then 执行命令else 执行命令fi[root@shell ~]# cat tesh.sh#!/bin/bashif [ -f $1 ];then echo $1文件存在else echo $1文件不存在fi[root@shell ~]# bash test.sh /etc/hosts/etc/hosts文件存在[root@shell ~]# bash test.sh /blogggggggggg/blogggggggggg文件不存在[root@shell ~]# bash test.sh /etc/etc文件不存在# '/etc/ 是目录,-f 判断为假'多分支(多个条件、多个结果)
if [ 条件表达式1 ];then 命令elif [ 条件表达式2 ];then 命令elif [ 条件表达式3 ];then 命令elif [ 条件表达式4 ];then 命令else 命令fi实战案例
🌰 案例 1 — 传入 2 个整数比较大小
[root@shell ~]# cat diff.sh#!/bin/bashread -p "输入两个整数空格间隔: " num1 num2if [[ ! "$num1" =~ ^[0-9]+$ ]];then echo 请输入整数 exitfiif [[ ! "$num2" =~ ^[0-9]+$ ]];then echo 请输入整数 exitfi
if [ $num1 -eq $num2 ]then echo "$num1 = $num2"# 这里输出的是一整个字符串 --> 整体elif [ $num1 -gt $num2 ]then echo "$num1 > $num2"else echo "$num1 < $num2"fi✨ 颜色输出
| 颜色码 | 颜色 |
|---|---|
\e[31m | 红色 |
\e[32m | 绿色 |
\e[33m | 黄色 |
\e[34m | 蓝色 |
\e[0m | ==重置颜色== |
💡 核心使用公式
echo -e "\e[颜色码m 你的文字 \e[0m"- 必须使用
echo -e,普通的echo不会解析\e转义符。 - 文字后面务必加上
\e[0m重置颜色,否则终端后续的所有输出都会变成该颜色
#!/bin/bash
echo -e "\e[34m====== 系统管理菜单 ======\e[0m"echo -e "\e[32m(1)启动服务\e[0m"echo -e "\e[33m(2)查看日志\e[0m"echo -e "\e[31m(3)停止服务\e[0m"echo -e "\e[34m=========================\e[0m"
read -p "请输入选项(1|2|3|4): " choice
if [ "$choice" == "1" ]; then# 这里是字符串判断 echo -e "\e[32m✔ 服务启动成功\e[0m"elif [ "$choice" -eq 2 ]; then# 这里是数字比较(整数) echo -e "\e[33m⚠ 正在读取日志...\e[0m"elif [ $choice == "3" ]; then echo -e "\e[31m✘ 服务已停止\e[0m"else echo -e "\e[31m✘ 无效选项\e[0m"fi📌 进阶小贴士(避免重复写颜色码)
在实际写脚本时,每次都写 \e[31m...\e[0m 会很繁琐,推荐在脚本开头定义变量:
RED='\e[31m'GREEN='\e[32m'YELLOW='\e[33m'BLUE='\e[34m'RESET='\e[0m'
# 使用时直接拼接,简洁且不易漏掉重置符echo -e "${GREEN}操作成功${RESET}"echo -e "${RED}错误:文件不存在${RESET}"📌 小结
本章从变量子串出发,覆盖了 Shell 编程中最常用的变量操作和条件判断:
| 章节 | 核心知识点 | 关键语法 |
|---|---|---|
| 变量子串 — 长度 | 统计字符串长度 | ${#变量} ⭐ |
| 变量子串 — 删除 | 从前往后/从后往前删除 | # ## % %% |
| 变量子串 — 替换 | 替换第一个/替换全部 | / // |
| 数值运算 | 6 种运算方式 | $(()) ⭐ bc let |
| 整数比较 | 6 个比较符号 | -eq -ne -gt -ge -lt -le |
| 文件判断 | 6 个文件测试 | -f -d -e -r -w -x |
| 字符串判断 | 相等/不等/长度 | = != -n -z |
| 正则判断 | [[ ]] 中 =~ 匹配 | ^ $ [a-z] + |
| if 判断 | 单分支/双分支/多分支 | if-then-elif-else-fi |
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!




