Shell通配符与正则:*?[]{} 通配,基础正则匹配(grep 入门)
------ 当你的脚本需要"精准定位"文件或文本
"通配符是文件系统的模糊搜索,正则是文本世界的精确制导。搞混它们,就像用渔网捞针。"------ 一个被误删日志文件逼出模式匹配洁癖的DBA
上个月,我们的一位同事想清理 电科金仓 KES 的旧归档日志。
他写了这样一条命令:
bash
rm /opt/Kingbase/archives/*2023*.wal
本意是删 2023 年的日志,结果把 archive_2023_backup.wal 也删了------那是人工保留的灾备副本。
问题在哪?
他以为 *2023* 是"包含 2023 的文件",但没意识到通配符在 Shell 层展开,不理解语义,只匹配字符。
更糟的是,他没用 -i 确认,也没先 ls 预览。
那一刻我意识到:不懂通配符和正则边界的运维,是在雷区跳舞。
今天,我们就把这两套模式系统彻底分开讲清------什么场景用什么,怎么用才安全。
一、通配符(Globbing):Shell 的文件名匹配
通配符由 Shell 自身 在命令执行前展开,用于匹配文件路径。
常见通配符:
| 符号 | 含义 | 示例 |
|---|---|---|
* |
匹配任意长度字符(不含 /) |
*.log → 所有 .log 文件 |
? |
匹配单个字符 | file?.txt → file1.txt, fileA.txt |
[abc] |
匹配括号内任一字符 | log_[123].wal → log_1.wal, log_2.wal |
[a-z] |
匹配范围 | backup_2024[01-12].sql |
{a,b,c} |
大括号扩展(非通配符,但常混淆) | cp file.{txt,log} /backup/ |
关键特性:
- 只用于文件路径
- 由 Shell 展开,命令本身看不到
* - 不支持正则语法 (如
\d,+,())
安全实践:先 echo 或 ls 预览
bash
# 危险!直接删除
rm /opt/Kingbase/archives/*2023*.wal
# 安全!先看匹配了哪些
ls -l /opt/Kingbase/archives/*2023*.wal
# 或用 echo 查看展开结果
echo rm /opt/Kingbase/archives/*2023*.wal
二、正则表达式(Regex):文本内容的模式匹配
正则由命令内部引擎 处理(如 grep、sed),用于匹配文件内容或字符串。
grep 基础用法:
bash
# 默认使用基本正则(BRE)
grep "pattern" file
# 启用扩展正则(ERE),支持 + ? | ()
grep -E "pattern" file
常见正则元字符(ERE):
| 模式 | 含义 | 示例 |
|---|---|---|
. |
任意单字符 | a.c → abc, a2c |
* |
前一字符重复0次或多次 | ab*c → ac, abbc |
+ |
前一字符重复1次或多次(需 -E) |
ab+c → abc, abbbc(不含 ac) |
? |
前一字符出现0次或1次(需 -E) |
colou?r → color, colour |
^ |
行首 | ^ERROR → 以 ERROR 开头的行 |
$ |
行尾 | timeout$ → 以 timeout 结尾的行 |
[0-9] |
数字 | [0-9]{4} → 四位数(需 -E) |
\d |
不支持! Shell 正则不用 \d |
⚠️ 注意:Shell 通配符的
*和正则的*完全不是一回事!
三、真实场景:KES 日志分析中的正确用法
场景1:找出所有 2024 年 6 月的慢查询日志文件
bash
# 用通配符(匹配文件名)
ls /opt/Kingbase/log/kes_slowlog_202406*.log
场景2:从日志中提取执行时间 > 2000ms 的 SQL
bash
# 用正则(匹配文件内容)
grep -E "duration: [2-9][0-9]{3,}" /opt/Kingbase/log/kes.log
解释:
[2-9]:首位是 2-9(确保 ≥2000)[0-9]{3,}:后面至少3位数字(总长≥4)
场景3:统计各小时的错误日志量
bash
# 提取时间戳中的小时部分(如 14:30:22 → 14)
grep "FATAL\|PANIC" /opt/Kingbase/log/kes.log \
| grep -oE "[0-9]{2}:[0-9]{2}:[0-9]{2}" \
| cut -d: -f1 \
| sort \
| uniq -c
这里:
grep -oE:只输出匹配部分cut -d: -f1:取冒号分隔的第一段(小时)- 整个流程依赖正则精准提取
四、常见混淆点与避坑指南
混淆1:以为 *.log 是正则
bash
# 错误!这是通配符,只能用于文件路径
grep "*.log" file # 实际匹配字面量 "*." 后跟 "log"
✅ 正确写法(匹配任意 .log 结尾的行):
bash
grep "\.log$" file # BRE
grep -E "\.log$" file # ERE(推荐)
混淆2:在通配符中用正则语法
bash
# 错误!Shell 不认识 \d
ls /opt/Kingbase/archives/*\d{8}*.wal # 不会匹配任何文件
✅ 正确写法(用 [0-9]):
bash
ls /opt/Kingbase/archives/*[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]*.wal
# 或用 brace expansion(如果日期连续)
ls /opt/Kingbase/archives/*2024{01..12}{01..31}*.wal
混淆3:大括号 {} 是通配符?
bash
# 这不是通配符,是 Shell 的大括号扩展
echo file{1,2,3}.txt # 展开为 file1.txt file2.txt file3.txt
它在命令执行前由 Shell 处理,和 * 无关。
五、运维建议:安全第一
-
通配符操作前必预览
bashecho rm /path/to/*.wal # 先看展开结果 -
正则测试用小样本
bashhead -100 kes.log | grep -E "your_pattern" -
区分上下文
- 路径 → 通配符
- 内容 → 正则
-
默认用
grep -E扩展正则更接近现代正则习惯,避免
\{n,m\}这类繁琐转义。
结语:模式匹配是运维的"显微镜"
在管理像 电科金仓 KES 这类产生结构化日志与多实例文件的数据库系统时(技术背景参考),你每天都在和海量文本与文件打交道。
通配符帮你快速定位目标文件 ,
正则帮你精准提取关键信息。
用对工具,事半功倍;用错工具,灾难现场。
今日实践:
- 用通配符列出
/opt/Kingbase/log/下所有 2024 年的日志文件- 用
grep -E从这些文件中找出包含 "deadlock" 的行做完这个,你就真正"看清"了数据。
注:文中涉及的 KES(Kingbase Enterprise Server)是由电科金仓开发的企业级关系型数据库,其日志与归档文件管理常需结合通配符与正则实现高效运维。技术细节可参考 产品页面。