正则表达式 学习笔记
简介
正则表达式是一种用于描述和匹配字符串特定模式的工具。它依据一系列规则,通过一个字符串来表达一个特定的匹配模式。
正则表达式可以应用在各种语言或环境中,如 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()用于获取匹配的捕获组
附 - 相关网站
- 正则表达式测试网站:https://regex101.com/
- C++ 正则表达式:https://zh.cppreference.com/w/cpp/regex
- Python 正则表达式指南:https://docs.python.org/zh-cn/3/howto/regex.html
正则表达式 学习笔记
