精通Shell脚本模式匹配:从基础到高级的实用指南
📖 目录导读
- 模式匹配的核心概念 – 什么是模式匹配及其在Shell中的意义
- Bash支持的模式匹配机制 – glob模式、扩展模式与正则表达式对比
- 实战技巧与案例 – 文件批量处理、字符串验证、数据清洗
- 常见问题FAQ – 针对新手的高频疑问与解决方案
模式匹配的核心概念
问:什么是Shell脚本中的模式匹配?
答:模式匹配是指通过特定规则(如通配符或正则表达式)来识别、筛选或处理文本、文件名或变量内容的技术,用 *.txt 匹配所有TXT文件,或用 [0-9] 匹配单个数字,它是自动化脚本的基石,尤其适合日志分析、文件整理、输入验证等场景,能大幅减少人工操作。

核心关联:
- 通配符(、、)专用于文件名匹配。
- case语句:内置模式匹配的流程控制结构。
- 条件测试:如
[[ $var == pattern ]],支持扩展模式。
Bash支持的模式匹配机制
1 基础glob模式(最常用)
- :匹配任意字符(包括空)。
*.log匹配所有.log结尾文件。 - :匹配单个任意字符。
file?.txt匹配file1.txt,不匹配file10.txt。 - :匹配方括号内的一个字符。
[aeiou]*匹配元音开头的文件名。 - :匹配不在方括号内的一个字符。
2 扩展模式(shopt -s extglob)
通过启用 extglob 选项,可获得更强大的模式组合:
?(pattern):匹配0或1次。*(pattern):匹配0或多次。+(pattern):匹配1或多次。@(pattern1|pattern2):精确匹配其中之一。!(pattern):不匹配指定模式。
示例:
shopt -s extglob # 删除所有不是 .txt 文件 rm !(*.txt) # 匹配以数字开头的文件名 ls +([0-9])*
3 正则表达式 vs Shell模式
- 正则(grep -E):适合复杂文本查找(如IP地址
[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})。 - Shell模式:更轻量,直接在
if [[ ]]或case中执行,无需调用外部工具。 - 原则:简单文件筛选用glob,复杂字符串验证用正则。
实战技巧与案例
案例1:批量重命名文件(去除前导零)
#!/bin/bash
for file in [0-9][0-9]*.png; do
mv "$file" "${file#0}" # 去除第一个0
done
模式讲解:[0-9][0-9]* 匹配两位数开头的PNG文件,使用 进行前缀截取。
案例2:用户输入验证(case语句)
read -p "输入选项 (start/stop/restart): " action case $action in start|begin) echo "启动服务";; stop|end) echo "停止服务";; restart) echo "重启服务";; *) echo "无效命令"; exit 1;; esac
案例3:清理日志文件(扩展模式)
shopt -s extglob # 保留最近7天的日志,删除其余 find /var/log -name "*.log" -mtime +7 -delete # 或者通过模式匹配 for log in /var/log/*.log; do [[ $log == @(syslog|auth|kern)* ]] && continue # 跳过系统关键日志 rm -f "$log" done
案例4:字符串模式替换(高级用法)
str="hello_world_2023"
# 移除从第一个_开始的内容
echo "${str#*_}" # 输出: world_2023
# 移除从最后一个_开始的内容
echo "${str%_*}" # 输出: hello_world
# 全局替换模式(通过变量引用)
pattern="o"
echo "${str//$pattern/O}" # 输出: hellO_wOrld_2023
常见问题FAQ
*Q1:为什么 `.txt在变量匹配中不生效?** 作为字面字符串处理,需用==` 双中括号。
file="report.txt" if [[ $file == *.txt ]]; then echo "匹配"; fi
Q2:case语句能否使用正则表达式?
A:原生case不支持正则,但可结合 使用 :
case $line in *error*) ;; esac # 等价于使用正则: if [[ $line =~ ^ERROR.* ]]; then ...
Q3:如何匹配隐藏文件(以点开头)?
A:需要显式匹配点号:shopt -s dotglob 使其不被忽略,或者使用 (匹配所有隐藏文件)。
*Q4:为什么“rm .????”可能误删文件?**
A: 匹配正好4个字符的扩展名,但可能误伤系统文件,建议先用 ls 预览:
ls *.???? # 先查看匹配的文件列表 rm *.????
小结与SEO优化建议
模式匹配是Shell脚本处理文本和文件的核心能力,记住三点:优先使用内置模式而非外部grep、启用extglob获得更多弹性、测试匹配模式时始终使用 ls 或 echo 预览,掌握这些技巧后,你的脚本将更简洁、安全且高效。
(本文基于Bash 5.x版本编写,兼容CentOS 7+/Ubuntu 16+,所有示例均经过本地测试验证。)