Shell脚本条件判断#
条件判断是Shell脚本中实现逻辑控制的核心机制,允许脚本根据不同的条件执行不同的命令。本教程将详细介绍Shell中的各种条件判断语句,从基础的if语句到复杂的逻辑组合。
入门#
基本if语句#
if语句是Shell中最基本的条件判断结构,用于根据条件的真假执行不同的命令。
# 基本if语句
if [ condition ]; then
# 条件为真时执行的命令
fi
# 示例:检查文件是否存在
if [ -f "file.txt" ]; then
echo "文件存在"
fi
# if-else语句
if [ -f "file.txt" ]; then
echo "文件存在"
else
echo "文件不存在"
fi
# if-elif-else语句
if [ $USER = "root" ]; then
echo "您是root用户"
elif [ $USER = "admin" ]; then
echo "您是admin用户"
else
echo "您是普通用户"
fi测试命令#
Shell中的测试命令用于检查条件是否成立,有两种形式:[ condition ]和test condition。
# 测试文件状态
[ -f "file.txt" ] # 检查是否为普通文件
[ -d "dir" ] # 检查是否为目录
[ -e "path" ] # 检查路径是否存在
[ -s "file.txt" ] # 检查文件是否非空
# 测试字符串
[ -z "string" ] # 检查字符串是否为空
[ -n "string" ] # 检查字符串是否非空
[ "$a" = "$b" ] # 检查字符串是否相等
[ "$a" != "$b" ] # 检查字符串是否不相等
# 测试数字
[ $a -eq $b ] # 检查数字是否相等
[ $a -ne $b ] # 检查数字是否不相等
[ $a -lt $b ] # 检查a是否小于b
[ $a -le $b ] # 检查a是否小于等于b
[ $a -gt $b ] # 检查a是否大于b
[ $a -ge $b ] # 检查a是否大于等于b中级#
高级测试操作#
逻辑运算符#
# 逻辑与 -a 或 &&
if [ -f "file.txt" -a -r "file.txt" ]; then
echo "文件存在且可读"
fi
# 使用&&的另一种形式
if [ -f "file.txt" ] && [ -r "file.txt" ]; then
echo "文件存在且可读"
fi
# 逻辑或 -o 或 ||
if [ -f "file1.txt" -o -f "file2.txt" ]; then
echo "至少有一个文件存在"
fi
# 逻辑非 !
if [ ! -f "file.txt" ]; then
echo "文件不存在"
fi双括号语法#
(( ))语法用于算术运算和比较,支持C风格的语法。
# 算术比较
if (( 10 > 5 )); then
echo "10大于5"
fi
# 使用变量
x=10
y=5
if (( x > y )); then
echo "$x大于$y"
fi
# 支持的运算符: +, -, *, /, %, ==, !=, <, <=, >, >=, &&, ||, !双方括号语法#
[[ ]]语法是bash的扩展,提供了更强大的字符串处理能力。
# 字符串比较
if [[ "$string" == "test" ]]; then
echo "字符串匹配"
fi
# 模式匹配
if [[ "$string" == t* ]]; then
echo "字符串以t开头"
fi
# 正则表达式匹配
if [[ "$string" =~ ^[0-9]+$ ]]; then
echo "字符串是数字"
fi
# 逻辑运算符
if [[ -f "file.txt" && -r "file.txt" ]]; then
echo "文件存在且可读"
fi高级#
case语句#
case语句用于多条件分支判断,比多个if-elif语句更简洁。
# 基本case语句
case $variable in
pattern1)
# 匹配pattern1时执行的命令
;;
pattern2)
# 匹配pattern2时执行的命令
;;
*)
# 匹配所有其他情况时执行的命令
;;
esac
# 示例:菜单选择
read -p "请选择 (1-3): " choice
case $choice in
1)
echo "您选择了选项1"
;;
2)
echo "您选择了选项2"
;;
3)
echo "您选择了选项3"
;;
*)
echo "无效选择"
;;
esac
# 模式匹配
case $filename in
*.txt)
echo "文本文件"
;;
*.sh)
echo "Shell脚本"
;;
*.jpg|*.png)
echo "图片文件"
;;
*)
echo "其他文件"
;;
esac条件表达式#
命令执行结果作为条件#
# 命令执行成功(退出状态为0)作为条件
if grep -q "pattern" "file.txt"; then
echo "文件中包含pattern"
fi
# 命令执行失败作为条件
if ! cp "file.txt" "backup.txt"; then
echo "复制失败"
fi
# 组合命令
if command1 && command2; then
echo "两个命令都执行成功"
fi特殊条件判断#
# 检查命令是否存在
if command -v git > /dev/null 2>&1; then
echo "git已安装"
else
echo "git未安装"
fi
# 检查操作系统类型
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
echo "Linux系统"
elif [[ "$OSTYPE" == "darwin"* ]]; then
echo "macOS系统"
elif [[ "$OSTYPE" == "cygwin" ]]; then
echo "Cygwin"
elif [[ "$OSTYPE" == "msys" ]]; then
echo "MSYS/MinGW"
else
echo "未知系统: $OSTYPE"
fi
# 检查用户权限
if [ $(id -u) -eq 0 ]; then
echo "您是root用户"
else
echo "您不是root用户"
fi大师#
高级条件结构#
单行条件语句#
# 单行if语句
if [ -f "file.txt" ]; then echo "文件存在"; fi
# 使用&&和||的简写形式
[ -f "file.txt" ] && echo "文件存在" || echo "文件不存在"
# 命令执行的条件判断
command && echo "成功" || echo "失败"嵌套条件#
# 嵌套if语句
if [ -d "dir" ]; then
if [ -w "dir" ]; then
if [ -x "dir" ]; then
echo "目录存在且可写可执行"
else
echo "目录存在且可写但不可执行"
fi
else
echo "目录存在但不可写"
fi
else
echo "目录不存在"
fi
# 复杂的case语句
case $option in
[0-9])
echo "单个数字"
;;
[a-z])
echo "小写字母"
;;
[A-Z])
echo "大写字母"
;;
*)
case $option in
quit|exit)
echo "退出"
;;
help|?)
echo "帮助"
;;
*)
echo "其他选项"
;;
esac
;;
esac性能优化#
# 短路评估
# 避免不必要的测试
if [ -f "file.txt" ] && [ $(wc -l < "file.txt") -gt 10 ]; then
echo "文件存在且行数超过10"
fi
# 先检查最可能失败的条件
# 例如,文件存在性检查比内容检查快
if [ -f "large_file.txt" ] && grep -q "pattern" "large_file.txt"; then
echo "文件存在且包含pattern"
fi
# 使用缓存避免重复计算
file_count=$(ls -l | wc -l)
if [ $file_count -gt 0 ]; then
echo "目录中有$file_count个文件"
# 后续可以重复使用$file_count变量
fi无敌#
高级条件技巧#
函数式条件#
# 使用函数作为条件
is_root() {
[ $(id -u) -eq 0 ]
}
if is_root; then
echo "您是root用户"
else
echo "您不是root用户"
fi
# 返回状态的函数
check_file() {
local file="$1"
[ -f "$file" ] && [ -r "$file" ] && [ -s "$file" ]
}
if check_file "important.txt"; then
echo "文件有效"
else
echo "文件无效"
fi动态条件#
# 动态生成条件
condition="-f file.txt -a -r file.txt"
if eval "[ $condition ]"; then
echo "条件成立"
fi
# 使用数组存储条件
conditions=(
"-f file.txt"
"-r file.txt"
"-s file.txt"
)
all_true=1
for cond in "${conditions[@]}"; do
if ! eval "[ $cond ]"; then
all_true=0
break
fi
done
if [ $all_true -eq 1 ]; then
echo "所有条件都成立"
else
echo "至少有一个条件不成立"
fi实用脚本示例#
系统检查脚本#
#!/bin/bash
# 系统检查脚本
echo "===== 系统检查 ====="
# 检查磁盘空间
if [ $(df -h / | tail -n 1 | awk '{print $5}' | sed 's/%//') -gt 90 ]; then
echo "警告:根分区空间不足"
else
echo "根分区空间正常"
fi
# 检查内存使用
if [ $(free -m | grep Mem | awk '{print $3}') -gt $(free -m | grep Mem | awk '{print $2}')*0.8 ]; then
echo "警告:内存使用过高"
else
echo "内存使用正常"
fi
# 检查关键服务
for service in sshd nginx mysql; do
if systemctl is-active --quiet $service; then
echo "服务 $service 运行正常"
else
echo "警告:服务 $service 未运行"
fi
done
echo "===== 检查完成 ====="备份脚本#
#!/bin/bash
# 备份脚本
backup_dir="/backup"
source_dirs=("/etc" "/home" "/var/www")
date=$(date +%Y-%m-%d)
# 检查备份目录
if [ ! -d "$backup_dir" ]; then
echo "创建备份目录: $backup_dir"
mkdir -p "$backup_dir"
fi
# 执行备份
for dir in "${source_dirs[@]}"; do
if [ -d "$dir" ]; then
backup_file="$backup_dir/$(basename $dir)-$date.tar.gz"
echo "备份 $dir 到 $backup_file"
tar -czf "$backup_file" "$dir"
# 检查备份是否成功
if [ $? -eq 0 ]; then
echo "备份成功"
else
echo "备份失败"
fi
else
echo "目录 $dir 不存在,跳过"
fi
done
# 清理旧备份(保留最近7天)
echo "清理7天前的旧备份"
find "$backup_dir" -name "*.tar.gz" -mtime +7 -delete
echo "备份任务完成"总结#
条件判断是Shell脚本中实现逻辑控制的核心机制,通过掌握if语句、case语句、测试命令和各种条件表达式,您可以创建更加智能和灵活的Shell脚本。从简单的文件检查到复杂的系统管理,条件判断无处不在。
随着您对Shell条件判断的理解不断深入,您将能够编写更加健壮、可靠的Shell脚本,处理各种复杂的场景和边缘情况。记住,良好的条件判断逻辑是构建高质量Shell脚本的基础。