正则表达式入门:基本元字符、量词、分组与反向引用
从一次日志排查开始
我记得刚接触HSM日志解析那会儿,面对几千行的原始日志,用grep匹配总是差那么一点。后来才明白,正则表达式就像一把精确的手术刀,能帮你从文本中准确切出想要的部分。
这一节咱们就聊聊正则的三大块:基本元字符、量词、分组与反向引用。说白了,掌握了它们,你写脚本解析HSM日志时会顺手很多。
基本元字符:字符的定位棋
正则最基本的元素就是元字符。每个元字符代表一类字符或一个特殊位置。
| 元字符 | 含义 | 例子 | 匹配示例 |
|---|---|---|---|
. | 匹配任意单个字符(除换行) | a.b | aab, a1b, a_b |
^ | 匹配行首 | ^Error | Error at line... |
$ | 匹配行尾 | done$ | task done |
\d | 匹配一个数字 [0-9] | \d{3} | 123 |
\w | 匹配字母、数字、下划线 | \w+ | hsmlog2023 |
\s | 匹配空白符(空格/tab/换行) | \s+ |
实践中我发现,刚开始容易把 . 当作“什么都行”,但要注意它默认不匹配换行。我在项目中就踩过这个坑——解析多行日志时,.* 死活不跨行,后来加了 s 修饰符才搞定。所以记得灵活用 \s\S 组合来跨行匹配。
量词:控制重复次数
光有元字符还不够,我们还要说“出现几次”。量词就是干这个的。
| 量词 | 含义 | 例子 | 匹配 |
|---|---|---|---|
* | 零次或多次 | ab* | a, ab, abb |
+ | 一次或多次 | ab+ | ab, abb(不匹配a) |
? | 零次或一次 | ab? | a, ab |
{n} | 恰好n次 | \d{4} | 2023 |
{n,} | 至少n次 | \d{2,} | 12, 123, 4567 |
{n,m} | n到m次 | \d{2,4} | 12, 123, 1234 |
大家要注意贪婪与懒惰匹配的区别。默认是贪婪的——匹配尽可能多的字符。比如用 .* 匹配 "abc"def" 时,会匹配到最后一个引号。如果你想要非贪婪,加个问号变成 .*?,它就匹配到第一个引号就停了。我写日志解析脚本时经常用非贪婪,避免吃进太多无关内容。
分组:把模式打包
圆括号 () 有两个作用:分组和捕获。分组可以让你对一组字符应用量词,比如 (ab)+ 匹配 ababab。更重要的是,分组会捕获匹配的内容,供后续引用。
举个例子,HSM日志中经常有 Session ID: 12345 这样的行。我们可以写:
Session ID: (\d+)
这样括号里的数字就被捕获到了第1组。如果你用shell的 grep -P 或 sed,就可以用 \1 引用它。
实用技巧: 在 sed 替换时,sed -E 's/(\d{4})-(\d{2})-(\d{2})/\3.\2.\1/' 可以把日期格式从 YYYY-MM-DD 变成 DD.MM.YYYY。我经常用这个批量改日志时间戳。
反向引用:复用已捕获的内容
反向引用允许你在同一个正则表达式中引用之前捕获的分组。比如你要匹配成对的标签:
<([a-z]+)>.+</\1>
这个模式能确保开始标签和结束标签名称一致,比如匹配 <error>something</error>,而不会匹配 <error></warning>。
注意: 反向引用在不同工具中语法略有差别。在 sed 中用 \1,在 Perl 兼容正则中用 \1 或 $1(替换时)。写shell脚本时,我习惯用 awk 的 match() 配合数组,更清晰。
综合示例:从HSM日志提取关键字段
假设我们有这样一行日志:
2024-01-15 14:32:18,INFO,HSM_Module,KeyGen,Success,Session=abc123,KeyID=0x4F2A
我们希望提取日期、级别、操作和KeyID。正则可以写成:
^(\d{4}-\d{2}-\d{2})\s+\d{2}:\d{2}:\d{2},(INFO|WARN|ERROR),.*?,.*?,(Success|Failure),Session=\w+,KeyID=(0x[0-9A-F]+)$
用 grep -Po 加上分组引用就能精确定位。我个人习惯把这种正则存成函数库,省的每次重写。
知识结构总览
下面这张图帮你梳理正则三大核心的关系:
核心总结: 正则不是背出来的,是用出来的。你只要记住三类元素:元字符定位字、量词控次数、分组抓内容。上手先从小模式开始,慢慢拼合。我在写HSM日志解析时,经常把复杂的正则拆成三四步,每步测试一行,最后再合并。这样做不容易出错,也方便调试。
好了,这一节的内容就到这儿。记得多用shell命令 grep -P、sed -E 和 awk 练手,把今天学的元字符、量词、分组用起来。