if [ 条件 ]; then
命令1
命令2
...
fi
if [ 条件 ]; then
条件为真时执行的命令
else
条件为假时执行的命令
fi
if [ 条件1 ]; then
命令1
elif [ 条件2 ]; then
命令2
else
命令3
fi
if [ 条件1 ]; then
if [ 条件2 ]; then
命令1
fi
else
命令2
fi
case 变量名 in
值1)
指令1
;;
值2)
指令2
;;
值3)
指令3
;;
*)
默认
esac
if [ $a -eq 10 ]; then ... # 等于
if [ $a -ne 10 ]; then ... # 不等于
if [ $a -gt 10 ]; then ... # 大于
if [ $a -lt 10 ]; then ... # 小于
if [ $a -ge 10 ]; then ... # 大于等于
if [ $a -le 10 ]; then ... # 小于等于
if [ "$str" = "hello" ]; then ... # 等于(注意用双引号)
if [ "$str" != "hello" ]; then ... # 不等于
if [ -z "$str" ]; then ... # 字符串为空
if [ -n "$str" ]; then ... # 字符串非空
if [ -e "file.txt" ]; then ... # 文件或目录存在
if [ -f "file.txt" ]; then ... # 文件存在且为普通文件
if [ -d "dir" ]; then ... # 目录存在
if [ -r "file.txt" ]; then ... # 文件可读
if [ -w "file.txt" ]; then ... # 文件可写
if [ -x "script.sh" ]; then ... # 文件可执行
# 使用 &&(逻辑与)
if [ -f "file.txt" ] && [ -r "file.txt" ]; then ...
# 使用 ||(逻辑或)
if [ $a -eq 1 ] || [ $a -eq 2 ]; then ...
# 使用 !(逻辑非)
if [ ! -d "dir" ]; then ...
#!/bin/bash
if [ -e "data.txt" ]; then
echo "文件存在"
cat data.txt
else
echo "文件不存在,创建中..."
touch data.txt
fi
#!/bin/bash
if [ $# -ne 2 ]; then
echo "错误:需要两个参数" >&2
echo "用法:$0 参数1 参数2" >&2
exit 1
else
echo "参数1: $1"
echo "参数2: $2"
fi
#!/bin/bash
read -p "请输入一个数字: " num
if [ "$num" -lt 0 ]; then
echo "负数"
elif [ "$num" -eq 0 ]; then
echo "零"
else
echo "正数"
fi
#!/bin/bash
read -p "请输入yes或no: " answer
if [ "$answer" = "yes" ]; then
echo "你选择了yes"
elif [ "$answer" = "no" ]; then
echo "你选择了no"
else
echo "无效输入"
fi
#!/bin/bash
if grep -q "error" log.txt; then
echo "日志中发现错误"
mail -s "系统异常" [email protected] < log.txt
else
echo "系统正常"
fi
#!/bin/bash
read -p "请输入年龄: " age
if [ "$age" -ge 18 ]; then
if [ "$age" -lt 60 ]; then
echo "成年人"
else
echo "老年人"
fi
else
echo "未成年人"
fi
由用户从键盘输入一个字符,并判断该字符是否为字母、数字或者其他字符, 并输出
相应的提示信息。
[root@kittod ~]# cat in.sh
#!/bin/bash
read -p "Please enter a character, press enter to continue: " KEY
case "$KEY" in
[a-z]|[A-Z])
echo "Input is letter"
;;
[0-9])
echo "Input is number"
;;
*)
echo "Input is other characters"
esac
[[ ]]
替代 [ ]
# [[ ]] 支持更复杂的表达式
if [[ "$str" == hello* ]]; then ... # 模式匹配
if [[ $a -gt 10 && $b -lt 20 ]]; then ... # 逻辑组合
(( ))
进行数值比较if (( a > 10 )); then ... # 无需引号,支持算术表达式
test
命令if test -f "file.txt"; then ... # 等同于 [ -f "file.txt" ]
空格问题:
[
和 ]
内部必须有空格,例如:
# 正确
if [ "$a" -eq 10 ]; then ...
# 错误(缺少空格)
if ["$a"-eq 10]; then ...
变量引用加引号:
防止变量为空时导致语法错误:
# 正确
if [ -z "$str" ]; then ...
# 错误(当 $str 为空时会变成 [ -z ],语法错误)
if [ -z $str ]; then ...
整数比较用 -eq
,而非 =
:
# 正确(数值比较)
if [ "$a" -eq 10 ]; then ...
# 错误(字符串比较)
if [ "$a" = 10 ]; then ...
语法结构 | 适用场景 | 示例 |
---|---|---|
[ 条件 ] |
传统条件测试 | [ -f "file.txt" ] |
[[ 条件 ]] |
增强型条件测试(推荐) | [[ $a -gt 10 && $b -lt 20 ]] |
(( 条件 )) |
纯数值比较 | (( a > 10 )) |
test 条件 |
等同于 [ ] |
test -d "dir" |
合理使用 if
条件语句可以让脚本根据不同情况执行不同逻辑,增强脚本的灵活性和健壮性。
exit [N]
N
:可选参数,表示退出状态码(整数,范围通常为 0~255
)。
N
,exit
将返回最后一条命令的执行状态码。$?
变量在脚本外获取(例如在终端中执行 echo $?
)。0
:表示脚本正常执行完毕(无错误)。0
:表示脚本异常终止或执行过程中出现错误(常见值:1~255
)。状态码 | 含义说明 |
---|---|
1 |
通用错误(例如参数错误、文件不存在)。 |
2 |
Shell 内置命令错误(如 cd 命令失败)。 |
126 |
命令存在但不可执行(如脚本无执行权限)。 |
127 |
命令不存在(如拼写错误的命令)。 |
130 |
脚本被中断信号(如 Ctrl+C )终止。 |
255 |
非法退出状态码(超出范围的数值会被取模为 255 ,例如 exit 300 等价于 exit 44 )。 |
exit
的典型用法场景0
)#!/bin/bash
echo "脚本执行完成"
exit # 等价于 exit 0
echo $?
可获取状态码 0
。#!/bin/bash
# 检查文件是否存在
if [ ! -f "data.txt" ]; then
echo "错误:文件 data.txt 不存在!"
exit 1 # 退出并返回错误码 1
fi
echo "文件存在,继续执行..."
exit 0 # 正常退出
1
;否则返回 0
。#!/bin/bash
# 尝试创建目录
mkdir -p "/data/app"
if [ $? -ne 0 ]; then # $? 存储上一条命令的状态码
echo "创建目录失败!"
exit 2 # 返回错误码 2
fi
echo "目录创建成功"
exit 0
$?
判断前一条命令(mkdir
)是否执行成功,失败则退出并返回 2
。#!/bin/bash
check_disk_space() {
free_space=$(df -h / | awk 'NR==2 {print $4}')
if [ "$free_space" -lt "10G" ]; then
echo "磁盘空间不足!"
exit 100 # 在函数中直接退出脚本,返回 100
fi
}
check_disk_space
echo "磁盘空间充足" # 若空间不足,此行不会执行
exit 0
exit
会直接终止脚本,无需返回值传递。exit 300
等价于 exit 44
,因为 300 mod 256 = 44
)。exit
(...)
或管道)中执行 exit
,仅会终止子 Shell,不影响父脚本。例如: (
echo "子 Shell 开始"
exit 1 # 子 Shell 退出,返回码 1
)
echo "父脚本继续执行" # 此行会执行
echo $? # 输出 1(子 Shell 的退出码)
return
的区别exit
:用于终止整个脚本,并返回状态码给系统(适用于脚本主流程)。return
:用于终止当前函数,并返回状态码给调用者(仅在函数内部使用)。 func() {
return 5 # 函数返回 5,不终止脚本
}
func
echo $? # 输出 5(函数的返回值)
0
,错误时返回有意义的非零码(如 1
、2
等),便于外部脚本或监控工具判断执行结果。exit
,避免在循环或分支中无意义地退出。#!/bin/bash
# 检查当前用户是否为 root
if [ "$USER" != "root" ]; then
echo "错误:必须以 root 身份运行!" >&2 # 错误信息输出到 stderr
exit 1 # 非 root 用户,返回 1
fi
# 检查磁盘空间
free_space=$(df -BM / | awk 'NR==2 {print $4}' | tr -d 'M')
if [ "$free_space" -lt 100 ]; then
echo "警告:磁盘剩余空间不足 100MB!"
exit 2 # 空间不足,返回 2
fi
echo "脚本执行成功"
exit 0 # 正常退出,返回 0
$ ./script.sh # 非 root 用户执行
错误:必须以 root 身份运行!
$ echo $? # 查看状态码
1
$ sudo ./script.sh # root 用户执行且空间充足
脚本执行成功
$ echo $?
0
通过合理使用 exit
,可以让脚本更健壮、更易调试,尤其在自动化运维和脚本链调用中至关重要。
for
循环for 变量名 in 列表元素
do
命令序列
done
for fruit in apple banana cherry
do
echo "当前水果:$fruit"
done
输出:
当前水果:apple
当前水果:banana
当前水果:cherry
for file in /etc/*.conf
do
if [ -f "$file" ]; then
echo "文件:$file"
fi
done
for line in $(cat users.txt)
do
echo "用户:$line"
done
for
循环(适用于数值迭代)for ((初始值; 条件; 增量))
do
命令序列
done
i=1
)。i<=10
)。i++
)。示例:
for ((i=1; i<=5; i++))
do
echo "迭代次数:$i"
done
输出:
迭代次数:1
迭代次数:2
迭代次数:3
迭代次数:4
迭代次数:5
while
循环while [ 条件 ]
do
命令序列
done
sum=0
i=1
while [ $i -le 10 ]
do
sum=$((sum + i))
i=$((i + 1))
done
echo "1+2+...+10 = $sum"
输出:
1+2+...+10 = 55
while read -r line
do
echo "行内容:$line"
done < file.txt
while true
do
echo "无限循环中...(按 Ctrl+C 终止)"
sleep 1
done
until
循环until [ 条件 ]
do
命令序列
done
while
相反)。n=10
until [ $n -le 0 ]
do
echo "$n"
n=$((n - 1))
done
输出:
10
9
8
7
6
5
4
3
2
1
break
:跳出当前循环for i in 1 2 3 4 5
do
if [ $i -eq 3 ]; then
break # 当 i=3 时,跳出循环
fi
echo $i
done
输出:
1
2
continue
:跳过当前迭代,继续下一次循环for i in 1 2 3 4 5
do
if [ $i -eq 3 ]; then
continue # 当 i=3 时,跳过本次循环
fi
echo $i
done
输出:
1
2
4
5
break n
和 continue n
:控制多层循环n
表示跳出 / 跳过的循环层数(默认 n=1
,即当前层)。for i in a b c
do
for j in 1 2 3
do
if [ $j -eq 2 ]; then
break 2 # 跳出两层循环(即整个循环)
fi
echo "$i-$j"
done
done
输出:
a-1
# 删除所有 .bak 文件
for file in *.bak
do
rm -f "$file"
echo "已删除:$file"
done
echo -n "进度:["
for ((i=0; i<=10; i++))
do
sleep 0.5
echo -n "#"
done
echo "] 完成"
输出:
进度:##########] 完成
while true
do
read -p "是否继续?(y/n): " choice
case $choice in
[Yy])
echo "继续执行..."
;;
[Nn])
echo "退出程序"
break
;;
*)
echo "无效输入,请重新输入"
;;
esac
done
变量引用加引号:
避免列表元素包含空格时被错误分割:
# 错误(元素包含空格时分割错误)
for str in "hello world" "hi bash"
do
echo $str # 正确输出每个元素
done
避免无限循环:
在 while
/until
循环中确保条件最终为真 / 假,否则需用 Ctrl+C
强制终止。
多层循环性能:
嵌套循环可能影响性能,尽量优化循环逻辑或使用更高效的工具(如 awk
、sed
)。
arr=("apple" "banana" "cherry")
for fruit in "${arr[@]}"
do
echo "数组元素:$fruit"
done
arr=("a" "b" "c")
for i in "${!arr[@]}" # ${!arr[@]} 获取数组索引
do
echo "索引 $i:${arr[$i]}"
done
输出:
索引 0:a
索引 1:b
索引 2:c
循环类型 | 特点 | 适用场景 |
---|---|---|
for 循环 |
遍历固定列表或数值范围,简洁直观 | 批量处理文件、已知次数的任务 |
while 循环 |
条件为真时持续执行,适合未知次数的循环 | 读取文件、交互式操作 |
until 循环 |
条件为假时持续执行,逻辑与 while 相反 |
逆序计数、条件反转场景 |
break /continue |
控制循环流程,跳出或跳过迭代 | 复杂逻辑分支、提前终止循环 |