恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
Shell脚本条件语句详解与实战技巧
首页
资讯中心
/
Shell脚本条件语句详解与实战技巧
Shell脚本条件语句详解与实战技巧
发布时间:2026/8/3 7:27:56
1. Shell条件语句基础认知第一次在Linux终端里敲下if语句时那种既熟悉又陌生的感觉至今难忘。作为Shell脚本的三大逻辑结构之一条件语句就像交通信号灯控制着程序执行的走向。与C/java等语言不同Shell的条件判断有着自己独特的语法体系和易踩的坑。在Shell环境下条件语句主要分为if-then和case两种形式。if适用于需要连续判断的场景比如检查文件是否存在后再判断内容case则更适合多分支匹配像处理用户输入选项这类场景。实际运维中80%的脚本错误都源于条件语句的语法错误或逻辑缺陷。经验之谈Shell脚本的方括号[ ]前后必须保留空格这是新手最容易忽略的语法细节。写成if [$var -eq 0]会导致脚本直接报错。2. if语句深度解析2.1 基础if结构实战最基础的if结构由if-then-fi组成判断条件放在if和then之间。测试一个变量值的典型写法if [ $count -gt 10 ]; then echo 超过阈值 fi这里的[ ]实际上是test命令的简写-gt表示大于比较。Shell中数值比较必须使用特定参数-eq等于-ne不等于-lt小于-gt大于-le小于等于-ge大于等于2.2 多条件组合技巧当需要同时满足多个条件时可以使用-a(and)或-o(or)连接if [ -f /tmp/log -a -r /tmp/log ]; then echo 文件存在且可读 fi更现代的写法是使用双中括号[[ ]]支持更自然的逻辑运算符if [[ $age -gt 18 $gender male ]]; then echo 成年男性 fi避坑指南字符串比较必须用双引号包裹变量否则空变量会导致语法错误。写成if [ $var value ]比if [ $var value ]风险更高。2.3 文件测试的18种姿势Shell提供了丰富的文件测试运算符-e文件存在-f是普通文件-d是目录-s文件非空-r/-w/-x可读/可写/可执行典型应用场景if [ ! -d /backup ]; then mkdir -p /backup echo 创建备份目录 fi3. case语句进阶应用3.1 基础语法结构case语句就像Shell中的switch适合处理多个固定模式匹配case $1 in start) service start ;; stop) service stop ;; *) echo Usage: $0 {start|stop} ;; esac每个模式以)结束用;;终止当前分支。最后的*)是默认匹配项。3.2 模式匹配黑科技case支持通配符匹配*任意字符?单个字符[abc]字符集合|或关系例如处理文件扩展名case $filename in *.jpg|*.png) echo 图片文件 ;; *.sh) echo 脚本文件 ;; esac3.3 实战服务控制脚本综合应用案例#!/bin/bash case $1 in start|restart) /usr/local/bin/service.sh start ;; stop) kill $(cat /var/run/service.pid) ;; status) ps -p $(cat /var/run/service.pid) /dev/null echo Running || echo Stopped ;; *) echo Invalid argument: $1 exit 1 ;; esac4. 条件测试的底层原理4.1 test vs [ ] vs [[ ]]test是原始命令如test -f file[ ]是test的别名最后参数必须是][[ ]]是bash增强版支持正则和模式匹配执行效率对比time for i in {1..1000}; do test -f /etc/passwd; done time for i in {1..1000}; do [ -f /etc/passwd ]; done time for i in {1..1000}; do [[ -f /etc/passwd ]]; done4.2 数值计算的正确姿势Shell默认进行字符串比较数值计算推荐使用$(( ))算术扩展let命令bc高精度计算错误示例if [ $count 10 ] # 按ASCII比较字符串正确写法if (( count 10 )) # 算术比较5. 企业级应用与排错5.1 生产环境最佳实践总是检查变量是否存在${var:-default} # 使用默认值 ${var:?Error} # 报错退出防御性编程[[ -z $user_input ]] die 输入不能为空日志记录关键判断logger -t script 判断用户$UID权限5.2 经典错误排查报错[: missing ] 原因方括号内没有空格报错unexpected operator 原因使用了bash语法但以sh运行逻辑错误字符串与数字比较混淆 解决统一使用[[ ]]或(( ))报错too many arguments 原因变量未引号导致分词5.3 性能优化技巧减少子进程调用# 慢 if grep -q pattern file; then # 快 if [[ $(file) ~ pattern ]]; then提前终止条件[[ $# -eq 0 ]] { usage; exit 1; }使用函数封装复杂判断is_valid_ip() { [[ $1 ~ ^[0-9]\.[0-9]\.[0-9]\.[0-9]$ ]] }6. 扩展应用场景6.1 交互式菜单设计结合case实现用户菜单while true; do echo 1. 安装 echo 2. 配置 echo 3. 退出 read -p 选择 opt case $opt in 1) install ;; 2) configure ;; 3) break ;; *) echo 无效选项 ;; esac done6.2 参数校验框架通用参数检查函数validate_args() { case $1 in --help|-h) usage; exit 0 ;; --version|-v) show_version; exit 0 ;; --*|-*) die 未知选项: $1 ;; *) return # 非选项参数 esac }6.3 安全检测脚本示例检查系统安全的典型条件判断check_security() { case $(uname -r) in 2.6.*|3.*) echo 内核版本过旧 ;; esac if [[ $(umask) ! 0077 ]]; then echo umask设置不安全 fi [[ -x /tmp/exploit ]] rm -f /tmp/exploit }在近十年的Shell脚本开发中我发现条件语句的可靠性直接决定脚本的健壮性。建议每个关键判断都添加错误处理重要脚本则应该实现--dry-run模式来验证逻辑。记住好的Shell脚本不是写出来的是调试出来的。