简介
概括而言,使用正则表达式处理字符串的流程包括:用正则表达式定义要匹配的字符串的规则,然后对目标字符串进行匹配,最后对匹配到的结果进行操作。C++ 的 regex 库提供了用于表示正则表达式和匹配结果的基本类型,以及使用这些基本类型作为参数或返回结果(通过参数来返回,不是函数的返回值)的搜寻、匹配、替换等函数
转义字符
在讲具体方法之前,我们先了解下C++中使用正则表达式需要注意的一个问题:转义字符
#include <iostream>
#include <regex>
using namespace std;
int main() {
cout << regex_match("666", regex("\d+")) << endl; //结果为0,需要转义字符'\'
cout << regex_match("666", regex("\\d+")) << endl; //结果为1,完全匹配
return 0;
}
对上述例子解释:
+ 匹配一次或多次
\d 匹配一个数字字符
regex_match
基本概念
match是全文匹配,即要求整个字符串符合匹配规则
#include <iostream>
#include <regex>
using namespace std;
int main() {
cout << regex_match("666", regex("\d+")) << endl; //结果为0,需要转义字符'\'
cout << regex_match("666", regex("\\d+")) << endl; //结果为1,完全匹配
return 0;
}
上述方法返回值为bool值,主要用于if条件表达式中
匹配结果
更多的时候我们希望能够获得匹配结果(字符串),对结果进行操作。这时就需要对匹配结果进行存储,共有两种存储方式。
match_results<string::const_iterator> result;
smatch result; //推荐
匹配结果实例
#include <iostream>
#include <regex>
using namespace std;
int main() {
string str = "Hello_2019";
smatch result;
regex pattern("(.{5})_(\\d{4})"); //匹配5个任意单字符 + 下划线 + 4个数字
if (regex_match(str, result, pattern))
{
cout<<"数组表示方式:"<<endl;
cout << result[0] << endl; //完整匹配结果,Hello_2019
cout << result[1] << endl; //第一组匹配的数据,Hello
cout << result[2] << endl; //第二组匹配的数据,2019
cout<<endl;
cout<<"另一种表示方式:"<<endl;
cout<<endl;
cout<< result.str() << endl; //完整结果,Hello_2019
cout<< result.str(1) << endl; //第一组匹配的数据,Hello
cout << result.str(2) << endl; //第二组匹配的数据,2019
}
cout<<endl;
//遍历结果
cout<<"遍历存储结果:"<<endl;
for (int i = 0; i < result.size(); ++i)
cout << result[i] << endl;
return 0;
}
result[]与result.str()这两种方式能够获得相同的值,我更喜欢用数组形式的。
在匹配规则中,以括号()的方式来划分组别,实例中的规则共有两个括号,所以共有两组数据。
regex_search
基本概念
search是搜索匹配,即搜索字符串中存在符合规则的子字符串。
match与search一比较便知
#include <iostream>
#include <regex>
using namespace std;
int main() {
cout << regex_match("666", regex("\\d")) << endl; //结果为0
cout << regex_match("666", regex("\\d+")) << endl; //结果为1
cout << regex_search("666", regex("\\d")) << endl; //结果为1
return 0;
}
实例分析
#include <iostream>
#include <regex>
using namespace std;
int main() {
string str = "Hello 2019, Bye 2018";
smatch result;
regex pattern("\\d{4}"); //匹配四个数字
//迭代器声明
string::const_iterator iterStart = str.begin();
string::const_iterator iterEnd = str.end();
string temp;
while (regex_search(iterStart, iterEnd, result, pattern))
{
temp = result[0];
cout << temp << " ";
iterStart = result[0].second; //更新搜索起始位置,搜索剩下的字符串
}
cout<<endl;
return 0;
}
只需要利用迭代器就可以很轻松的访问到所有匹配的结果值。
regex_replace
基本概念
replace是替换匹配,即可以将符合匹配规则的子字符串替换为其他字符串。
#include <iostream>
#include <regex>
using namespace std;
int main() {
string str = "Hello_2019!";
regex pattern("Hello");
cout << regex_replace(str, pattern, "") << endl; //输出:_2019,将Hello替换为""
cout << regex_replace(str, pattern, "Hi") << endl; //输出:Hi_2019,将Hello替换为Hi
return 0;
}
拓展
除了直接替换以外,还有可以用来调整字符串内容(缩短、顺序等)。
#include <iostream>
#include <regex>
using namespace std;
int main() {
string str = "Hello_2019!";
regex pattern2("(.{3})(.{2})_(\\d{4})");
//匹配3个任意字符+2个任意字符+下划线+4个数字
cout << regex_replace(str, pattern2, "$1$3") << endl;
//输出:Hel2019,将字符串替换为第一个和第三个表达式匹配的内容
cout << regex_replace(str, pattern2, "$1$3$2") << endl;
//输出:Hel2019lo,交换位置顺序
return 0;
}
匹配忽略大小写
基本概念
有时我们希望能够匹配的时候忽略大小写,这时候就要用到regex的语法选项了。
#include <iostream>
#include <regex>
using namespace std;
int main() {
cout << regex_match("aaaAAA", regex("a*", regex::icase)) << endl; //结果为1
cout << regex_match("aaaAAA", regex("a*")) << endl; //结果为0
return 0;
}
还是来个实际题目做做吧? 讲这么多概念要会用嗷~
Codeforces Round #130 (Div. 2), problem: (A) Dubstep
题目大意
把所有WUB变成空格,如果有几个WUB连在一起,只能有一个空格,输出的开头必须是字母
题解
使用正则表达式
#include <iostream>
#include <regex>
using namespace std;
int main() {
string str,str1;
while(cin>>str){
str1 = regex_replace(str,regex("(WUB)+")," ");
string s;
s=regex_replace(str1,regex("^\\s"),"");
cout<<s<<endl;
}
return 0;
}
/(^\s*)|(\s*$)/g表示空格开头或者空格结尾
^ 是开始
\s 是空白
* 表示0个或多个
| 是或者
$ 是结尾
g 表示全局
学如逆水行舟,不进则退