一、什么是匹配模式?

匹配模式是在正则表达式主体之外设置的选项,用于改变整个正则表达式的匹配方式。它们不匹配具体字符,而是控制如何进行匹配。

基本语法:通常放在正则表达式的开始或结束分隔符之后。

  • JavaScript: /pattern/flags(如 /abc/gi)
  • Python: re.compile(pattern, flags) 或 re.search(pattern, string, flags)
  • 其他语言:类似语法

二、核心匹配模式详解

1. 忽略大小写模式(Case-Insensitive)

标志:i
作用:使匹配不区分字母的大小写。

示例:

const pattern = /hello/i;
console.log(pattern.test("Hello")); // true
console.log(pattern.test("HELLO")); // true
console.log(pattern.test("hElLo")); // true

Python 示例:

import re
pattern = re.compile(r'hello', re.IGNORECASE)  # 或 re.I
print(bool(pattern.search("HELLO World")))  # True

应用场景:

  • 用户名匹配
  • 搜索功能
  • 文件扩展名检查(.jpg、.JPG、.Jpg)

2. 全局匹配模式(Global)

标志:g
作用:找到所有匹配项,而不是在第一个匹配后停止。

对比示例:

const text = "apple apple apple";

// 没有 g 标志 - 只找到第一个匹配
const pattern1 = /apple/;
console.log(text.match(pattern1)); 
// 结果: ["apple"] (只有一个)

// 有 g 标志 - 找到所有匹配
const pattern2 = /apple/g;
console.log(text.match(pattern2)); 
// 结果: ["apple", "apple", "apple"] (全部三个)

注意事项:

  • 在 JavaScript 中,带有 g 标志的正则表达式对象会维护 lastIndex 属性,影响后续匹配。
  • 在 Python 中,findall() 和 finditer() 方法本身就匹配所有出现,不需要 g 标志。

3. 多行模式(Multiline)

标志:m
作用:改变 ^ 和 $ 的行为,使它们分别匹配每一行的开头和结尾,而不是整个字符串的开头和结尾。

对比示例:

const text = "第一行\n第二行\n第三行";

// 没有 m 标志 - ^ 和 $ 匹配整个字符串的开头和结尾
const pattern1 = /^第二行$/;
console.log(pattern1.test(text)); // false

// 有 m 标志 - ^ 和 $ 匹配每行的开头和结尾
const pattern2 = /^第二行$/m;
console.log(pattern2.test(text)); // true

应用场景:

  • 处理多行文本日志
  • 解析配置文件
  • 处理用户输入的多行文本

4. 点号匹配所有模式(Dot All / Single Line)

标志:s
作用:使点号 . 匹配包括换行符在内的所有字符。(默认情况下 . 不匹配换行符)

对比示例:

const text = "第一行\n第二行";

// 没有 s 标志 - . 不匹配换行符
const pattern1 = /第一行.第二行/;
console.log(pattern1.test(text)); // false

// 有 s 标志 - . 匹配包括换行符的所有字符
const pattern2 = /第一行.第二行/s;
console.log(pattern2.test(text)); // true

Python 示例:

import re
text = "第一行\n第二行"

# 没有 DOTALL 标志
pattern1 = re.compile(r'第一行.第二行')
print(bool(pattern1.search(text)))  # False

# 有 DOTALL 标志
pattern2 = re.compile(r'第一行.第二行', re.DOTALL)  # 或 re.S
print(bool(pattern2.search(text)))  # True

应用场景:

  • 匹配跨越多行的注释(如 /* 注释内容 */)
  • 处理包含换行符的文本块

5. 详细模式(Verbose / Extended)

标志:x
作用:允许在正则表达式中使用空白字符和注释,使复杂的正则表达式更易读。

示例:

import re

# 紧凑难读的写法
pattern1 = r'\d{3}-\d{2}-\d{4}|\d{9}'

# 使用详细模式,可以添加空格和注释
pattern2 = re.compile(r"""
    \d{3}-\d{2}-\d{4}   # 带连字符的SSN格式: 123-45-6789
    |                   # 或者
    \d{9}               # 无连字符的SSN格式: 123456789
""", re.VERBOSE)  # 或 re.X

注意事项:

  • 在详细模式下,如果要匹配字面空格,需要转义或使用字符组 [ ]
  • 此模式主要用在需要复杂、可读性强的正则表达式时
  • JavaScript 原生不支持此模式

6. Unicode 模式(Unicode)

标志:u
作用:启用完整的 Unicode 匹配支持。

示例:

const text = "🐘🚀✨";

// 没有 u 标志 - 可能无法正确处理 Unicode
const pattern1 = /\p{Emoji}/;  // 错误
// console.log(pattern1.test(text)); // 可能报错或返回错误结果

// 有 u 标志 - 正确支持 Unicode 属性
const pattern2 = /\p{Emoji}/gu;
console.log([...text.matchAll(pattern2)]); 
// 结果: [["🐘"], ["🚀"], ["✨"]]

Unicode 属性示例:

  • \p{L}:任何语言的字母
  • \p{N}:数字
  • \p{Emoji}:表情符号
  • \p{Script=Han}:汉字

7. 粘性匹配模式(Sticky)

标志:y
作用:从目标字符串的 lastIndex 位置开始匹配,且必须从该位置开始就匹配成功。

与全局匹配的区别:

  • g:在字符串中搜索所有匹配位置
  • y:只从 lastIndex 开始匹配,如果该位置不匹配则失败

示例:

const text = "abcabc";

// 全局匹配 - 找到所有 "abc"
const patternG = /abc/g;
console.log(patternG.exec(text)); // ["abc"] at index 0
console.log(patternG.exec(text)); // ["abc"] at index 3

// 粘性匹配 - 只从指定位置匹配
const patternY = /abc/y;
patternY.lastIndex = 0;
console.log(patternY.exec(text)); // ["abc"] at index 0

patternY.lastIndex = 1; // 从位置1开始
console.log(patternY.exec(text)); // null (位置1是"b",不匹配"abc")

应用场景:

  • 词法分析器(lexer)
  • 需要精确控制匹配位置的场景

三、模式组合使用

多个模式标志可以组合使用:

JavaScript:

// 忽略大小写 + 全局匹配 + 多行模式
const pattern = /^hello/igm;

Python:

import re

# 使用 | 运算符组合多个标志
pattern = re.compile(r"""
    ^hello      # 行首的hello
    .*          # 任意字符
    world$      # 行尾的world
""", re.IGNORECASE | re.MULTILINE | re.DOTALL | re.VERBOSE)

四、内联模式(局部模式)

在某些正则引擎中,可以在正则表达式内部使用 (?标志) 语法来局部启用或禁用模式:

语法:

  • (?i):从此处开始忽略大小写
  • (?-i):从此处开始区分大小写
  • (?i:subpattern):只对子表达式启用忽略大小写

示例:

# 整体不忽略大小写,但"example"部分忽略
CaseSensitive(?i:example)CaseSensitive

# 前半部分忽略大小写,后半部分区分
(?i)prefix-(?-i)suffix

支持情况:这种语法在 PCRE(Perl Compatible Regular Expressions)和部分语言中支持,但 JavaScript 原生不支持。

五、各语言标志对照表

模式JavaScriptPythonJava.NETPHP
忽略大小写ire.IGNORECASE/re.IPattern.CASE_INSENSITIVERegexOptions.IgnoreCasei
全局匹配g(自动)(多次调用)(自动)g
多行模式mre.MULTILINE/re.MPattern.MULTILINERegexOptions.Multilinem
点号匹配所有sre.DOTALL/re.SPattern.DOTALLRegexOptions.Singlelines
详细模式❌ 不支持re.VERBOSE/re.XPattern.COMMENTSRegexOptions.IgnorePatternWhitespacex
Unicodeu(默认)(默认)(默认)u
粘性匹配y❌ 不支持❌ 不支持❌ 不支持❌ 不支持

六、最佳实践与注意事项

  1. 性能考虑:某些模式组合可能影响性能,特别是在处理大文本时。
  2. 模式冲突:注意 m 和 s 模式对 ^、$ 和 . 行为的影响。
  3. 语言差异:不同语言对模式的支持程度不同,使用时需查阅具体文档。
  4. 可读性:对于复杂正则表达式,使用详细模式 (x) 大大提高可维护性。
  5. 测试:使用在线工具(如 regex101.com)测试不同模式下的匹配效果。

常用模式组合

场景推荐模式组合说明
搜索替换gi全局、不区分大小写
多行文本处理gm 或 gms全局、多行模式(可选点号匹配所有)
复杂模式编写x(结合其他模式)详细模式,提高可读性
Unicode 文本处理gu全局、Unicode 支持

掌握这些匹配模式可以让你更精确地控制正则表达式的行为,适应各种复杂的文本处理场景。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐