0%

C++中简单正则表达式的使用

参考文档:
Reference <regex>
microsoft Learn->Microsoft C++、C 和 汇编程序->C++ 标准库->C++ 标准库头文件->regex

regex 库的简单应用

  • std::regex
    • regex 是 char basic_regex 的类型定义,这个类模板描述包含正则表达式的对象,这个类模板的对象可以传递给模板函数 regex_match、regex_search 和 regex_replace。它还传递合适的文本字符串自变量,以搜索与正则表达式匹配的文本
  • std::smatch
    • smatch 是 string match_results 的类型定义,类模板描述一个对象,该对象用于控制由正则表达式搜索生成的 sub_match<BidIt> 类型元素不可修改的序列。每个元素指向与该元素对应的捕获组匹配的子序列。
  • std::regex_search
    • regex_search 函数用于搜索正则表达式匹配项。仅在其操作数序列中成功搜索到其正则表达式 re 时,每个模板函数才返回 true。 采用 match_results 对象的函数将其成员设置为反映搜索是否成功,以及如果成功,正则表达式中的各种捕获组所捕获的内容。
    • This function returns true if the expression is found anywhere in the target sequence, even if the sequence contains more characters that are not part of the match before or after the match. For a function that returns true only when the entire sequence matches, see regex_match.
    • std::regex_search(str, matches, pattern)
  • std::regex_match
    • regex_match 函数用于测试正则表达式是否与整个目标字符串相匹配,每个模板函数仅在整个操作数序列 str 与正则表达式参数 re 完全匹配时才返回 true
    • 请使用 regex_search 匹配目标序列中的子字符串,并使用 regex_iterator 查找多个匹配。 采用 match_results 对象的函数将其成员设置为反映匹配是否成功,以及如果成功,正则表达式中的各种捕获组所捕获的内容
    • std::regex_match(str, pattern)
    • std::regex_match(str, matches, pattern)
    • std::regex_match(str.cbegin(), str.cend(), matches, pattern) 其中 cbegin 与 cend 中的 c for const
  • std::sregex_iterator
    • string regex_iterator 的类型定义,用于循环访问匹配结果
    • using sregex_iterator = regex_iterator<string::const_iterator>;
    • std::sregex_iterator it(str.begin(), str.end(), pattern);
  • std::regex_iterator::regex_iterator
    • 用于循环访问匹配结果
    • std::regex_iterator<std::string::iterator> rit(str.begin(), str.end(), pattern);
  • 正则表达式与 R
    • 使用 R"()" 来定义一个原始字符串字面量(raw string literal)。这种语法允许你在字符串中使用特殊字符(比如反斜杠 \)而不需要进行转义
  • 常见的正则表达式编写规则
    • 普通字符匹配:
      • 普通字符(例如字母、数字)会直接匹配它们自己。例如:a 匹配字符 “a”
    • 特殊字符:
      • \ :用于转义特殊字符,使其成为普通字符。例如:. 匹配句号
      • . :匹配除换行符之外的任意字符
      • ^ :匹配行的开始位置
      • $ :匹配行的结束位置
    • 字符类别:
      • [ ] :用于定义一个字符集合,匹配其中的任意一个字符
        例如:[aeiou] 匹配任意一个元音字母,[^aeiou] 匹配任意一个非元音字母
    • 预定义字符类别:
      • \d :匹配任意一个数字(等价于 [0-9])
      • \D :匹配任意一个非数字字符
      • \w :匹配任意一个字母、数字或下划线字符(等价于 [a-zA-Z0-9_])
      • \W :匹配任意一个非字母、数字或下划线字符
    • 重复次数:
      • * :匹配前面的字符零次或多次
      • + :匹配前面的字符一次或多次
      • ? :匹配前面的字符零次或一次
      • {n} :匹配前面的字符恰好 n 次
      • {n,} :匹配前面的字符至少 n 次
      • {n,m} :匹配前面的字符至少 n 次,但不超过 m 次
    • 分组和选择:
      • ( ) :用于将表达式分组,以便对整个组应用重复次数或其他操作
      • | :用于在两个或多个表达式之间选择一个。
    • 转义字符:
      • \ :用于转义特殊字符,使其成为普通字符。例如:\ 匹配字符 “”
    • 开始和结束锚点:
      • ^ :匹配字符串的开始位置
      • $ :匹配字符串的结束位置

regex 库的应用范例

regex_search example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// regex_search example
#include <iostream>
#include <string>
#include <regex>

int main ()
{
std::string s ("this subject has a submarine as a subsequence");
std::smatch m;
std::regex e ("\\b(sub)([^ ]*)"); // matches words beginning by "sub"

std::cout << "Target sequence: " << s << std::endl;
std::cout << "Regular expression: /\\b(sub)([^ ]*)/" << std::endl;
std::cout << "The following matches and submatches were found:" << std::endl;

while (std::regex_search (s,m,e)) {
for (auto x:m) std::cout << x << " ";
std::cout << std::endl;
s = m.suffix().str();
}

return 0;
}
1
2
3
4
5
6
7
Output:
Target sequence: this subject has a submarine as subsequence
Regular expression: /\b(sub)([^ ]*)/
The following matches and submatches were found:
subject sub ject
submarine sub marine
subsequence sub sequence

regex_match example

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
34
35
36
37
38
39
40
41
42
43
44
// regex_match example
#include <iostream>
#include <string>
#include <regex>

int main ()
{

if (std::regex_match ("subject", std::regex("(sub)(.*)") ))
std::cout << "string literal matched\n";

const char cstr[] = "subject";
std::string s ("subject");
std::regex e ("(sub)(.*)");

if (std::regex_match (s,e))
std::cout << "string object matched\n";

if ( std::regex_match ( s.begin(), s.end(), e ) )
std::cout << "range matched\n";

std::cmatch cm; // same as std::match_results<const char*> cm;
std::regex_match (cstr,cm,e);
std::cout << "string literal with " << cm.size() << " matches\n";

std::smatch sm; // same as std::match_results<string::const_iterator> sm;
std::regex_match (s,sm,e);
std::cout << "string object with " << sm.size() << " matches\n";

std::regex_match ( s.cbegin(), s.cend(), sm, e);
std::cout << "range with " << sm.size() << " matches\n";

// using explicit flags:
std::regex_match ( cstr, cm, e, std::regex_constants::match_default );

std::cout << "the matches were: ";
for (unsigned i=0; i<cm.size(); ++i) {
std::cout << "[" << cm[i] << "] ";
}

std::cout << std::endl;

return 0;
}
1
2
3
4
5
6
7
8
Output:
string literal matched
string object matched
range matched
string literal with 3 matches
string object with 3 matches
range with 3 matches
the matches were: [subject] [sub] [ject]

regex_iterator example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// regex_iterator constructor
#include <iostream>
#include <string>
#include <regex>

int main ()
{
std::string s ("this subject has a submarine as a subsequence");
std::regex e ("\\b(sub)([^ ]*)"); // matches words beginning by "sub"

std::regex_iterator<std::string::iterator> rit ( s.begin(), s.end(), e );
std::regex_iterator<std::string::iterator> rend;

while (rit!=rend) {
std::cout << rit->str() << std::endl;
++rit;
}

return 0;
}
1
2
3
4
Output:
subject
submarine
subsequence

A specific application

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
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <string>
#include <regex>
#include <iomanip>

int main() {
double value;
std::cin >> value;
std::regex pattern(R"(\d+\.\d+[ef])");
std::smatch matches;
std::string format;
std::cin >> format;
if (std::regex_match(format, matches, pattern))
{
std::string format_str = matches.str();
std::regex digits(R"(\d+)");
std::sregex_iterator it(format_str.begin(), format_str.end(), digits);
std::smatch digits_1 = *it;
std::smatch digits_2 = *(++it);
int min_wide = std::stoi(digits_1.str());
int precision = std::stoi(digits_2.str());
char mode = format_str.back();
switch (mode)
{
case 'f':
{
std::cout << std::setw(min_wide) << std::setprecision(precision)
<< std::fixed << value << std::endl;
break;
}
case 'e':
{
std::cout << std::setw(min_wide) << std::setprecision(precision)
<< std::scientific << value << std::endl;
break;
}
default:
break;
}
}
return 0;
}
1
2
3
4
5
6
input: 
0.8539
6.3f

output:
0.854