正则表达式 学习笔记

简介

正则表达式是一种用于描述和匹配字符串特定模式的工具。它依据一系列规则,通过一个字符串来表达一个特定的匹配模式。

正则表达式可以应用在各种语言或环境中,如 C++/Python/Javascript/Bash,主要出现在文本搜索替换的场景下。

规则

正则表达式中包括普通字符和特殊字符(元字符):普通字符匹配自身;而元字符不匹配自身,用于表达一些特殊规则。元字符包括:. ^ $ * + ? { } [ ] \ | ( )

接下来介绍正则表达式中的一些基础规则。

转义

\ 可以转义元字符,使其在表达式中匹配其本身,如 \[, \\。而 \ 转义普通字符时则表示一些特殊规则。

字符类

[] 用来指定一种字符类,表示可以同时匹配多种字符,如 [abc], [a-zA-Z0-9]

^ 可以将字符类的限定范围取反,如 [^a-c]

\^ 以外的元字符在字符类中将作为普通字符身份作用。

预定义字符集

\ 还可以用来表示一些预定义字符集:

  • \w 匹配任意字母/数字或下划线,相当于 [a-zA-Z0-9_]
  • \d 匹配任意数字字符,相当于 [0-9]
  • \s 匹配任意空白字符,相当于 [ \t\n\r\f\v]
  • \W, \D, \S 表示它们对应的补集,即 [^a-zA-Z0-9_], [^0-9], [^ \t\n\r\f\v]
  • . 匹配除换行符以外的所有字符

这些预定义字符集可以被包含在字符类中,如 [\dabc]

分组

() 可以将匹配目标分组,从而指明或运算或限定符的作用对象。此时,被分组匹配到的内容会被捕获,可以通过反向引用使用,这样的分组称为捕获组。有时为了提高效率需要不捕获内容,可以使用非捕获组 (?:),如 (?:[a-z])

形如 (?) 的表达式除非捕获组以外都不真正匹配任何内容,而是起到一些特殊限定作用,例如前瞻后顾

或表达式

| 用来构成或表达式,表示可以同时匹配多种字符串,如 a (cat|dog)

限定符

限定符用于限定内容的出现次数:

  • ? 表示其左边的内容可以出现 0 次或 1 次
  • * 表示其左边的内容可以出现 0 次或任意多次
  • + 表示其左边的内容可以出现 1 次或多次
  • {} 限定其左边内容的出现次数范围,如 abc{6}, ab(c){1,3}(边界可以省略,默认为 0 和无穷)

零宽断言

零宽断言元字符可以指定匹配目标的位置:

  • ^ 用于匹配行首的内容,如 ^a
  • $ 用于匹配行尾的内容,如 a$
  • \A 用于匹配字符串首,如 \Aa
  • \Z 用于匹配字符串尾,如 a\Z
  • \d 用于匹配单词(指 \w 构成的子串)的边界,如 \ba, a\b
  • \B 用于匹配单词的非边界位置

贪婪匹配

包含限定符的表达式会匹配尽可能多的字符,称为贪婪匹配。

? 出现在限定符右边时,可以将正则表达式中的限定符切换为非贪婪匹配,即匹配尽可能少的字符,如 a*?, a??

反向引用

\ 加上数字字符可以引用捕获组的内容,如 \2 可以引用第二个捕获组匹配到的实际内容。

引用到的内容将继续用于匹配,例如 (1)\1 可以匹配子串 “11”。

前瞻和后顾

前瞻和后顾用于限定匹配目标的上下文内容,类似于零宽断言。其中前瞻限定匹配目标的后方内容,而后顾则与之反向:

  • (?=) 表示前瞻,如 \$(?=\d) 可以匹配金额 “$100” 中的 “$“
  • (?!) 表示负前瞻(即对条件取反),如 \$(?!\D) 相当于 \$(?=\d)
  • (?<=) 表示后顾,如 (?<=\$)\d 可以匹配金额 “$100” 中的 “100”
  • (?<!) 表示负后顾,与负前瞻同理

使用

C++

C++11 引入的 <regex> 库提供了一系列利用正则表达式的工具,例如:

  • std::regex 类表示一个字符串正则表达式
  • std::smatch 类表示一个匹配结果
  • std::regex_search() 用于匹配一个正则表达式到字符串的任意部分
  • std::regex_replace() 用于格式化替换正则表达式在目标字符串中出现的位置

Python

Python 的 re 模块包含正则表达式相关工具,例如:

  • re.Pattern 类表示一个模式对象
  • re.Match 类表示一个匹配对象
  • re.compile() 用于将正则表达式字符串编译为模式对象
  • re.search() 用于寻找第一个匹配位置,并返回匹配对象;re.Pattern.search() 类似
  • re.sub() 用于替换匹配子串;re.Pattern.sub() 类似
  • re.Match.group() 用于获取匹配的捕获组

附 - 相关网站


作者

Cu_OH_2

发布于

2024-05-17

更新于

2024-06-19

许可协议