正则表达式
正则表达式
该文记录正则表达式定义、语法、示例。
正则表达式
1 定义
正则表达式(英语:Regular expression
,常简写为 regex
、regexp
或 RE
),又称规律表达式、正则表示式、正则表示法、规则表达式、常规表示法,是计算机科学概念,用简单字符串来描述、匹配文中全部匹配指定格式的字符串,现在很多文本编辑器都支持用正则表达式搜索、取代匹配指定格式的字符串。
2 语法
一个正则表达式通常被称为一个模式(pattern
),为用来描述或者匹配一系列匹配某个句法规则的字符串。大部分正则表达式的形式都有如下的结构:
2.1 选择
- 竖线
|
: 代表选择(即或集),具有最低优先级。
2.2 数量限定
某个字符后的数量限定符用来限定前面这个字符允许出现的个数。最常见的数量限定符包括+
、?
和*
(不加数量限定则代表出现一次且仅出现一次):
- 加号
+
: 代表前面的字符必须至少出现一次。(1次或多次)。 - 问号
?
: 代表前面的字符最多只可以出现一次。(0次或1次)。 - 星号
*
: 代表前面的字符可以不出现,也可以出现一次或者多次。(0次、1次或多次)。
2.3 匹配
- 圆括号
()
: 可以用来定义操作符的范围和优先度。
2.4 优先权
优先权 | 符号 |
---|---|
最高 | \ |
高 | () 、(?:) 、(?=) 、[] |
中 | * 、+ 、? 、{n} 、{n,} 、{n,m} |
低 | ^ 、$ 、中介字符 |
次最低 | 串接,即相邻字符连接在一起 |
最低 | \| |
2.5 常见规则
字符 | 描述 |
---|---|
\ | 将下一个字符标记为一个特殊字符(File Format Escape )、或一个原义字符(Identity Escape ,有 ^$()*+?.[\{\| 共计12个)、或一个向后引用(backreferences )、或一个八进制转义符。例如,n 匹配字符n 。\n 匹配一个换行符。\\ 匹配 \ 而 \( 则匹配 ( 。 |
^ | 匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 \n 或 \r 之后的位置。 |
$ | 匹配输入字符串的结束位置。如果设置了 RegExp 对象的 Multiline 属性,$ 也匹配 \n 或 \r 之前的位置。 |
* | 匹配前面的子表达式零次或多次。例如,zo* 能匹配 z 、zo 以及 zoo 。*等价于{0,}。 |
+ | 匹配前面的子表达式一次或多次。例如, zo+ 能匹配 zo 以及 zoo ,但不能匹配 z 。+ 等价于 {1,} 。 |
? | 匹配前面的子表达式零次或一次。例如, do(es)? 可以匹配 does 中的 do 和 does 。? 等价于 {0,1} 。 |
{n} | n 是一个非负整数。匹配确定的n 次。例如, o{2} 不能匹配 Bob 中的 o ,但是能匹配 food 中的两个 o 。 |
{n,} | n 是一个非负整数。至少匹配n 次。例如, o{2,} 不能匹配 Bob 中的 o ,但能匹配 foooood 中的所有o。 o{1,} 等价于 o+ 。 o{0,} 则等价于 o 。 |
{n,m} | m 和n 均为非负整数,其中n<=m 。最少匹配n 次且最多匹配m 次。例如, o{1,3} 将匹配 fooooood 中的前三个o。 o{0,1} 等价于 o? 。请注意在逗号和两个数之间不能有空格。 |
. | 匹配除 \r \n 之外的任何单个字符。要匹配包括 \r \n 在内的任何字符,请使用像 (. | \r | \n) 的模式。 |
(pattern) | 匹配 pattern 并获取这一匹配的子字符串。该子字符串用于向后引用。所获取的匹配可以从产生的Matches集合得到,可带数量后缀。 |
(?:pattern) | 匹配 pattern 但不获取匹配的子字符串,不存储匹配的子字符串用于向后引用。这在使用或字符 ( | ) 来组合一个模式的各个部分是很有用。例如 industr(?:y | ies) 就是一个比 industry | industries 更简略的表达式。 |
(?=pattern) | 正向肯定预查(look ahead positive assert),在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如, Windows(?=95 | 98 | NT | 2000) 能匹配 Windows2000 中的 Windows ,但不能匹配 Windows3.1 中的 Windows 。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。 |
(?!pattern) | 正向否定预查(negative assert),在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如 Windows(?!95 | 98 | NT | 2000) 能匹配 Windows3.1 中的 Windows ,但不能匹配 Windows2000 中的 Windows 。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始 |
(?<=pattern) | 反向(look behind)肯定预查,与正向肯定预查类似,只是方向相反。例如, (?<=95 | 98 | NT | 2000)Windows 能匹配 2000Windows 中的 Windows ,但不能匹配 3.1Windows 中的 Windows 。 |
(?<!pattern) | 反向否定预查,与正向否定预查类似,只是方向相反。例如 (?<!95 | 98 | NT | 2000)Windows 能匹配 3.1Windows 中的 Windows ,但不能匹配 2000Windows 中的 Windows 。 |
[xyz] | 字符集合(character class)。匹配所包含的任意一个字符。例如, [abc] 可以匹配 plain 中的 a 。特殊字符仅有反斜线\保持特殊含义,用于转义字符。其它特殊字符如星号、加号、各种括号等均作为普通字符。脱字符^如果出现在首位则表示负值字符集合;如果出现在字符串中间就仅作为普通字符。连字符 - 如果出现在字符串中间表示字符范围描述;如果如果出现在首位(或末尾)则仅作为普通字符。右方括号应转义出现,也可以作为首位字符出现。 |
[^xyz] | 排除型字符集合(negated character classes)。匹配未列出的任意字符。例如, [^abc] 可以匹配 plain 中的 plin 。 |
[a-z] | 字符范围。匹配指定范围内的任意字符。例如, [a-z] 可以匹配 a 到 z 范围内的任意小写字母字符。 |
[^a-z] | 排除型的字符范围。匹配任何不在指定范围内的任意字符。例如, [^a-z] 可以匹配任何不在 a 到 z 范围内的任意字符。 |
\b | 匹配一个单词边界,也就是指单词和空格间的位置。例如, er\b 可以匹配 never 中的 er ,但不能匹配 verb 中的 er 。 |
\B | 匹配非单词边界。 er\B 能匹配 verb 中的 er ,但不能匹配 never 中的 er 。 |
\cx | 匹配由x指明的控制字符。x的值必须为A-Z 或a-z 之一。否则,将 c 视为一个原义的 c 字符。 |
\d | 匹配一个数字字符。等价于 [0-9] 。注意 Unicode 正则表达式会匹配全角数字字符。 |
\D | 匹配一个非数字字符。等价于 [^0-9] 。 |
\f | 匹配一个换页符。等价于 \x0c 和 \cL 。 |
\n | 匹配一个换行符。等价于 \x0a 和 \cJ 。 |
\r | 匹配一个回车符。等价于 \x0d 和 \cM 。 |
\s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [\f\n\r\t\v] 。注意Unicode正则表达式会匹配全角空格符。 |
\S | 匹配任何非空白字符。等价于[^\f\n\r\t\v] 。 |
\t | 匹配一个制表符。等价于 \x09 和 \cI 。 |
\v | 匹配一个垂直制表符。等价于 \x0b 和 \cK 。 |
\w | 匹配包括下划线的任何单词字符。等价于 [A-Za-z0-9_] 。注意Unicode正则表达式会匹配中文字符。 |
\W | 匹配任何非单词字符。等价于 [^A-Za-z0-9_] 。 |
3 示例
原始字符串字面值(raw string literal
)是 C++11
引入的新特性,使用方式 R"()"
。
原始字符串是原生的、不加处理的字符串,所见即所得,引号、斜杠无需 \
转义。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <string>
#include <regex>
int main()
{
std::string fun1 = "virtual bool is_empty() const;";
std::string fun2 = "Test operator=(const Test& test);";
// 这是一个判断是否是函数的正则
std::regex regRaw(R"((virtual\s+)?(\w+)(\s+)(\w+(?:=|==)?)?\((.*)\)(\s+const)?;)");
// 结果的第一个字符串是整个字符串
std::smatch results;
bool ret = std::regex_match(fun1, results, regRaw);
for (auto result : results)
{
if (result.matched != false)
{
std::cout << result << std::endl;
}
}
ret = std::regex_match(fun2, results, regRaw);
for (auto result : results)
{
if (result.matched != false)
{
std::cout << result << std::endl;
}
}
return 0;
}
参考
本文由作者按照 CC BY 4.0 进行授权