深入理解Bash脚本中的条件分支:if else实战指南

张开发
2026/6/5 14:24:13 15 分钟阅读
深入理解Bash脚本中的条件分支:if else实战指南
1. 为什么你需要掌握Bash条件分支每次看到新手在终端里重复输入相同的命令序列时我都忍不住想递给他一个Bash脚本。而脚本中最能体现智能化的部分就是if else条件分支。想象一下你家的智能空调室温高于28度自动制冷低于18度自动制热其他情况保持通风——这就是典型的条件分支逻辑。我在自动化部署脚本中频繁使用条件判断。比如最近给团队写的自动化测试脚本需要根据不同的测试类型单元测试、集成测试、压力测试执行不同的测试套件。没有条件分支的话就得写三个独立的脚本文件维护起来简直是噩梦。Bash的条件判断语法确实有些反直觉特别是对那些熟悉C/Java等语言的人来说。记得我第一次写Bash脚本时因为漏写了then前面的分号调试了半小时。但一旦掌握核心要点你会发现它比多数编程语言的条件判断更灵活——特别是结合Linux命令使用时。2. if else基础语法全解析2.1 标准语法结构先看这个每天都会用到的备份脚本片段if [[ ! -d /backup ]]; then mkdir -p /backup echo 备份目录已创建 else echo 备份目录已存在 fi这里有几个关键点需要注意if和[[之间必须要有空格就像你叫朋友全名时会自然停顿一样条件判断使用双中括号[[ ]]比单中括号[ ]更安全能避免很多意外的语法解析错误then必须另起一行或者用分号与条件语句连接如if [[条件]]; then2.2 多条件组合当需要同时满足多个条件时可以这样写if [[ -f lockfile ]] [[ $(wc -l log.txt) -gt 100 ]]; then echo 检测到锁文件且日志超过100行执行清理 rm lockfile truncate log.txt --size 0 fi表示逻辑与||表示逻辑或。我建议总是用双中括号包裹每个独立条件这样可读性更好。3. 实战中的高级技巧3.1 正则匹配的妙用处理用户输入时正则匹配能省去大量字符串处理代码。比如验证邮箱格式if [[ $email ~ ^[A-Za-z0-9._%-][A-Za-z0-9.-]\.[A-Za-z]{2,}$ ]]; then echo 邮箱格式正确 else echo 非法邮箱地址 2 exit 1 fi这里的~操作符会启用正则表达式匹配。注意模式字符串不要加引号否则会被当作普通字符串。3.2 文件测试的18般武艺Bash内置了大量文件测试操作符我整理了几个最实用的-e文件是否存在不区分类型-f是普通文件非目录/设备文件-d是目录-s文件存在且非空-r/-w/-x是否可读/可写/可执行比如部署脚本中经常要检查配置文件config/etc/app.conf if [[ ! -f $config ]]; then cp default.conf $config elif [[ ! -s $config ]]; then echo 配置文件为空使用默认配置 2 cat default.conf $config fi4. 避坑指南我踩过的那些雷4.1 空格是隐形杀手这是我见过最常见的错误if [[$var value]] # 错误[[后需要空格 if [[ $varvalue ]] # 错误两侧需要空格正确的写法应该是if [[ $var value ]] # 所有关键位置都有空格4.2 整数比较的陷阱比较数字时用-eq/-ne/-gt/-lt等操作符比用/!更可靠count10 if (( count 5 )); then # 使用双括号算术比较 echo 超过阈值 fi或者更传统的写法if [[ $count -gt 5 ]]; then echo 超过阈值 fi4.3 命令返回值判断很多新手会这样判断命令是否成功if [[ $(grep error log.txt) ]]; then # 错误空字符串也会被当作false正确的做法是直接检查命令返回值if grep -q error log.txt; then # -q参数抑制输出 echo 发现错误日志 fi记得上次我写自动化部署脚本时因为没处理cd命令的返回值导致后续命令在错误目录执行把生产环境配置全删错了。现在我会强制检查每个关键命令cd /target || { echo 切换目录失败 2 exit 1 }5. 复杂条件处理的艺术5.1 case语句的优雅替代当有多个条件分支时可以用case替代多层if-elifcase $mode in start) start_service ;; stop) stop_service ;; restart) restart_service ;; *) echo Usage: $0 {start|stop|restart} 2 exit 1 esac5.2 使用函数封装条件逻辑对于复杂的条件判断我建议封装成函数is_valid_ip() { local ip$1 [[ $ip ~ ^[0-9]\.[0-9]\.[0-9]\.[0-9]$ ]] || return 1 IFS. read -ra nums $ip for num in ${nums[]}; do [[ $num -le 255 ]] || return 1 done return 0 } if is_valid_ip $user_input; then echo 有效IP地址 fi6. 调试技巧与性能优化6.1 调试模式下的条件追踪在脚本开头加上set -x可以显示每个条件的执行过程#!/bin/bash set -x if [[ $DEBUG true ]]; then verbose_mode--verbose fi运行时会显示 [[ true ]]6.2 避免过度条件嵌套当if嵌套超过三层时就该考虑重构了。这是我重构过的一个典型例子# 重构前 if [[ $os Linux ]]; then if [[ -f /etc/redhat-release ]]; then if grep -q CentOS /etc/redhat-release; then install_centos fi fi fi # 重构后 [[ $os ! Linux ]] exit 0 [[ ! -f /etc/redhat-release ]] exit 0 grep -q CentOS /etc/redhat-release install_centos7. 真实场景综合案例7.1 自动化部署脚本这是我为一个PHP项目写的部署脚本片段#!/bin/bash branch$1 target_dir/var/www/$branch # 检查参数 if [[ -z $branch ]]; then echo 请指定分支名称 2 exit 1 fi # 检查目录冲突 if [[ -e $target_dir ]]; then if [[ ! -d $target_dir ]]; then echo 目标路径被文件占用 2 exit 1 fi if [[ $(ls -A $target_dir) ]]; then read -p 目录非空确认覆盖[y/N] confirm [[ $confirm [yY] ]] || exit 0 fi fi # 执行部署 git clone -b $branch gitexample.com:project.git $target_dir || { echo 克隆仓库失败 2 exit 1 }7.2 系统监控告警脚本这个脚本每天通过cron运行检查服务器状态#!/bin/bash # 内存检查 mem_free$(free -m | awk /Mem/{print $4}) if (( mem_free 100 )); then send_alert 可用内存不足: ${mem_free}MB fi # 磁盘检查 disk_usage$(df -h / | awk NR2{print $5} | tr -d %) if (( disk_usage 90 )); then send_alert 根分区使用率: ${disk_usage}% fi # 服务检查 if ! systemctl is-active --quiet nginx; then send_alert Nginx服务异常 systemctl restart nginx fi写完这个脚本后我们服务器的小问题都能在用户投诉前自动修复了。特别是那个内存检查有次半夜发现内存泄漏及时重启服务避免了一场灾难。

更多文章