RegEx
是正则表达式(Regular Expression)的简称。它便于匹配、查找和管理文本。
基本匹配
点.
:允许匹配任何字符,包括特殊字符和空格。
字符集[abc]
:如果一个词中的字符可以是各种字符,我们就将所有的可选字符写进中括号[]
中。
否定字符集[^abc]
字母范围[a-z]
数字范围[0-9]
重复
星号*
:在字符后面加上*
,表示一个字符匹配0次或多次
加号+
:在字符后面加上+
,表示一个字符匹配1次或多次
问号?
:在字符后面加上+
,表示一个字符匹配0次或1次(即可选)
大括号 {}
{n}
确切出现n次{n,}
至少出现n次{,n}
至多出现n次{x,y}
出现x至y次
分组
我们可以对一个表达式进行分组,并用这些分组来引用或执行一些规则。为了给表达式分组,我们需要将文本包裹在()
中。
引用组
单词 ha 和 haa 分组如下。第一组用\1
来避免重复书写。这里的1
表示分组的顺序。请在表达式的末尾键入\2
以引用第二组。
文本:
ha-ha,haa-haa
正则:
(ha)-\1,(haa)-\2
结果:
ha-ha,haa-haa
括号(?:)
: 非捕获分组
您可以对表达式进行分组,并确保它不被引用捕获。例如,下面有两个分组,但我们用\1
引用的第一个组实际上是指向第二个组,因为第一个是未被捕获的分组。
文本:
ha-ha,haa-haa
正则:
(?:ha)-ha,(haa)-\1
结果:
ha-ha,haa-haa
竖线|
:允许一个表达式包含多个不同的分支。所有分支用|
分隔。和在字符层面上运作的字符集[abc]
不同,分支在表达式层面上运作。
转义字符 \
在书写正则表达式时,我们会用到 { } [ ] / \ + * . $^ | ?
这些特殊字符 。为了匹配这些特殊字符本身,我们需要通过\
将它们转义。
插入符^
:匹配字符串的开始
美元符号$
:匹配字符串的结束
单词字符\w
: 匹配字母、数字和下划线
非单词字符\W
:匹配除字母、数字和下划线之外的字符
数字字符\d
:仅用来匹配数字
非数字字符\D
:匹配除数字之外的字符
空白符\s
:仅匹配空白字符
非空白符\S
:匹配除空白符之外的字符
零宽断言
如果我们希望正在写的词语出现在另一个词语之前或之后,我们需要使用零宽断言
正向先行断言: (?=)
例如,我们要匹配文本中的小时值。只匹配后面有 PM 的数值
文本:
Date: 4 Aug 3PM
正则:
\d+(?=PM)
结果:
3PM
负向先行断言:(?!)
例如,我们要在文本中匹配除小时值以外的数字。我们需要在表达式后面使用负向先行断言 (?!),并在括号内的 ! 后面添加 PM,从而只匹配没有 PM 的数值。
文本:
Date: 4 Aug 3PM
正则:
\d+(?!PM)
结果:
4
正向后行断言: (?<=)
例如,我们要匹配文本中的金额数。只匹配前面带有 $ 的数字
正文:
Product Code: 1064 Price: $5
正则:
(?<=\$)\d+
结果
$5
负向后行断言: (?<!)
例如,我们要在文本中匹配除价格外的数字。只匹配前面没有 $ 的数字
正文:
Product Code: 1064 Price: $5
正则:
(?<!\$)\d+
结果:
1064
标志
标志改变表达式的输出。这就是标志也称为 修饰符 的原因。标志决定表达式是否将文本视作单独的行处理,是否区分大小写,或者是否查找所有匹配项。
全局标志/g
多行标志/m
忽略大小写标志/i
贪婪匹配
正则表达式默认执行贪婪匹配。这意味着匹配内容会尽可能长
正文:
ber beer beeer beeeer
贪婪匹配:
.*r
结果:
ber beer beeer beeeer
懒惰匹配:
.*?r
结果
ber
C++标准库
参见正则表达式库
regex_match
尝试匹配一个正则表达式到整个字符序列regex_search
尝试匹配一个正则表达式到字符序列的任何部分regex_replace
以格式化的替换文本来替换正则表达式匹配的出现位置
#include <iostream>
#include <iterator>
#include <string>
#include <regex>
int main()
{
std::string s = "Some people, when confronted with a problem, think "
"\"I know, I'll use regular expressions.\" "
"Now they have two problems.";
std::regex self_regex("REGULAR EXPRESSIONS",
std::regex_constants::ECMAScript | std::regex_constants::icase);
if (std::regex_search(s, self_regex)) {
std::cout << "Text contains the phrase 'regular expressions'\n";
}
// 匹配单词
std::regex word_regex("(\\w+)");
auto words_begin =
std::sregex_iterator(s.begin(), s.end(), word_regex);
auto words_end = std::sregex_iterator();
std::cout << "Found "
<< std::distance(words_begin, words_end)
<< " words\n";
// 输出长度大于6的单词
const int N = 6;
std::cout << "Words longer than " << N << " characters:\n";
for (std::sregex_iterator i = words_begin; i != words_end; ++i) {
std::smatch match = *i;
std::string match_str = match.str();
if (match_str.size() > N) {
std::cout << " " << match_str << '\n';
}
}
//替换
std::regex long_word_regex("(\\w{7,})");
std::string new_s = std::regex_replace(s, long_word_regex, "[$&]");
std::cout << new_s << '\n';
}