正则表达式

正则表达式(Regular Expression)终极指南


一、正则表达式基础概念

1. 什么是正则表达式?

正则表达式(Regex)是一种用于匹配、查找、替换文本模式的字符串,由普通字符和特殊字符(元字符)组成。它被广泛应用于:

  • 文本处理(搜索、替换、验证)
  • 数据清洗(提取结构化信息)
  • 编程语言(Python、JavaScript、Java等)
  • 开发工具(IDE、文本编辑器、命令行工具)

2. 正则表达式组成

  • 字面字符:普通字符(如 a1#)直接匹配自身。
  • 元字符:具有特殊含义的符号(如 .*^)。
  • 字符类:定义可匹配的字符集合(如 [a-z])。
  • 量词:指定匹配次数(如 +{3,5})。
  • 分组与捕获:将模式分组并捕获子匹配(如 (ab)+)。
  • 断言:指定匹配位置(如 ^$\b)。

二、元字符与转义

1. 基本元字符

元字符 含义 示例
. 匹配任意单个字符(除换行符) a.c → “abc”, “a1c”
^ 匹配字符串开始 ^Hello → 匹配行首的Hello
$ 匹配字符串结束 end$ → 匹配行末的end
\ 转义字符或特殊序列 \. 匹配字面点号
| 逻辑或 cat|dog → 匹配cat或dog
[...] 字符类,匹配其中任意一个字符 [aeiou] → 匹配元音字母
[^...] 否定字符类,匹配不在其中的字符 [^0-9] → 匹配非数字字符

2. 转义规则

  • 转义元字符:使用 \ 将元字符转为普通字符。 示例:\* 匹配星号,\\ 匹配反斜杠。
  • 预定义转义序列
    • \n:换行符
    • \t:制表符
    • \r:回车符
    • \d:数字(等价于 [0-9]
    • \D:非数字(等价于 [^0-9]
    • \s:空白字符(空格、制表符等)
    • \S:非空白字符
    • \w:单词字符(字母、数字、下划线)
    • \W:非单词字符

三、字符类与量词

1. 字符类

  • 范围表示[a-z] 匹配小写字母,[A-Za-z0-9] 匹配字母数字。
  • 预定义字符类
    • [:alnum:]:字母和数字(需在字符类内使用,如 [[:alnum:]]
    • [:alpha:]:字母
    • [:digit:]:数字
    • [:lower:]:小写字母
    • [:upper:]:大写字母

2. 量词

量词 含义 示例
* 0次或多次 a* → “”, “a”, “aa”
+ 1次或多次 a+ → “a”, “aa”
? 0次或1次 a? → “”, “a”
{n} 精确匹配n次 a{3} → “aaa”
{n,} 至少n次 a{2,} → “aa”, “aaa”
{n,m} 匹配n到m次 a{2,4} → “aa”, “aaa”

贪婪与非贪婪模式

  • 贪婪模式(默认):尽可能匹配最长字符串。 示例:a.*b 匹配 “aabcb” 中的整个字符串。
  • 非贪婪模式(加 ?):尽可能匹配最短字符串。 示例:a.*?b 匹配 “aabcb” 中的 “aab” 和 “ab”。

四、分组与捕获

1. 分组

  • 普通分组 ( ):将模式分组,可应用量词。 示例:(ab)+ → “ababab”。
  • 非捕获分组 (?: ):分组但不捕获。 示例:(?:ab)+ 匹配但不保存分组内容。

2. 捕获与引用

  • 捕获组编号:从左到右按左括号顺序编号(从1开始)。 示例:(\d{4})-(\d{2}) 捕获年(组1)和月(组2)。
  • 反向引用:使用 \n 引用分组内容(n为组号)。 示例:(\w+) \1 匹配重复单词(如 “the the”)。

3. 命名分组

  • 语法(?P<name>pattern)(Python)或 (?<name>pattern)(其他语言)。 示例:(?P<year>\d{4}) 捕获名为 “year” 的组。
  • 引用命名分组
    • Python:\g<year>
    • JavaScript:\k<year>

五、断言(Lookaround)

1. 基本断言

断言 语法 含义
正向先行断言 (?=pattern) 右侧必须匹配pattern
负向先行断言 (?!pattern) 右侧不能匹配pattern
正向后行断言 (?<=pattern) 左侧必须匹配pattern
负向后行断言 (?<!pattern) 左侧不能匹配pattern

2. 示例

  • 提取金额数字(?<=\$)\d+ → 匹配 “$100” 中的 “100”。
  • 密码强度验证: 至少包含大写字母、小写字母和数字: ^(?=.*[A-Z])(?=.*[a-z])(?=.*\d).{8,}$

六、常见正则表达式模式

1. 基础验证

  • 邮箱^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
  • URL^(https?://)?([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
  • IPv4地址^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$

2. 数据提取

  • HTML标签内容<h1>(.*?)</h1> → 匹配 <h1>标题</h1> 中的 “标题”。
  • 日志时间戳\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} → 匹配 “2023-10-01 12:34:56”。

3. 替换与格式化

  • 日期格式转换(YYYY/MM/DD → DD-MM-YYYY): 搜索:(\d{4})/(\d{2})/(\d{2}) 替换:\3-\2-\1
  • 删除多余空格: 搜索:\s+ 替换: (单个空格)

七、正则表达式性能优化

1. 避免回溯爆炸

  • 具体化模式:尽量使用精确匹配,避免模糊量词(如 .*)。
  • 使用原子组(Atomic Groups):某些引擎支持(如 (?>pattern)),禁止回溯。

2. 优化技巧

  • 锚定开始/结束:使用 ^$ 减少搜索范围。
  • 优先选择非贪婪量词:在复杂模式中减少回溯。
  • 避免嵌套量词:如 (a+)+ 可能导致指数级回溯。

八、各语言中的正则表达式

1. Python

  • 模块re
  • 函数
    • re.match():从字符串开始匹配
    • re.search():搜索整个字符串
    • re.findall():返回所有匹配结果
    • re.sub():替换匹配内容
  • 标志
    • re.IGNORECASEre.I):忽略大小写
    • re.MULTILINEre.M):多行模式

2. JavaScript

  • 语法/pattern/flags
  • 方法
    • String.match()
    • String.replace()
    • RegExp.test()
  • 标志
    • i:忽略大小写
    • g:全局匹配
    • m:多行模式

3. Java

  • java.util.regex.PatternMatcher
  • 方法
    • Pattern.compile()
    • Matcher.find()
    • Matcher.group()

九、工具与资源

1. 在线测试工具

2. 学习资源


十、正则表达式陷阱与最佳实践

1. 常见陷阱

  • 过度匹配:如 .* 可能意外匹配超长文本。
  • 未转义字符:如 +? 在字符类外需转义。
  • 性能问题:复杂模式可能导致超时。

2. 最佳实践

  • 注释与格式化:复杂正则使用 x 标志(忽略空格和注释)。 示例(Python):
    1
    2
    3
    4
    5
    
    pattern = re.compile(r'''
        ^\d{3}       # 匹配前3位数字
        -?            # 可选短横线
        \d{2}         # 后2位数字
    ''', re.VERBOSE)
    
  • 单元测试:为关键正则编写测试用例。
  • 优先使用内置解析器:如解析HTML/XML时,正则可能不够健壮。

十一、高级技巧

1. 递归匹配

  • 平衡括号匹配\((?:[^()]|(?R))*+\)(支持递归的正则引擎如PCRE)。

2. 条件匹配

  • 语法(?(condition)yes-pattern|no-pattern) 示例:匹配带区号的电话号码(可选区号):
    1
    
    ^(\(\d{3}\) )?\d{3}-\d{4}$ 
    

3. 模式修饰符

  • 内联修饰符:如 (?i) 忽略大小写,(?m) 多行模式。 示例:(?i)hello 匹配 “Hello”、“HELLO”。

十二、总结图表

正则表达式速查表

类别 语法 示例
字符类 [abc], [^abc] [aeiou], [^0-9]
量词 *, +, ?, {n,m} a{2,4}, .*?
分组与捕获 ( ), (?: ), (?P<>) (\d+), (?P<year>\d{4})
断言 (?= ), (?<= ) (?=\d), (?<=@)\w+
转义字符 \d, \s, \w \d{3}-\d{4}