C++ 正则表达式

1,628 阅读2分钟

C++正则表达式

头文件 #include<regex>

#include<regex>
regex_match 函数是整个字符串完全匹配。返回值:匹配成功返回1,失败返回0
string mobile = "13666666668";
regex re("1\\d{10}");  //注:正则表达式中的\b在C++中需要转义\才能被认为是\b
if (regex_match(mobile, re)) {  //因此使用的是\\b
  cout << "是电话号码!\n";
} else {
  cout << "不是电话号码!\n";
}

可以配合cmatch和smatch类分别存放char*或 string类型字符串的匹配结果,遍历即可获得匹配的值。

分组匹配字符串并且输出匹配的内容

str = "this is text string!";
regex sre("this(.*?)te(.*?)tring!", regex::icase);
smatch sm;
regex_match(str, sm, sre);
for (unsigned i = 0; i < sm.size(); ++i) {  
    cout << "[" << sm[i] << "] \n";
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iJF1495j-1619770130484)(file:///C:\Users\017813~1\AppData\Local\Temp\ksohtml17320\wps14.jpg)] C++11提供的正则表达式库操作string对象,模式使用regex (本质是std::basic_regex)进行初始化,通过regex_match进行匹配,从而产生smatch(本质是match_results对象)。

regex_search 寻找第一个与正则表达式匹配的子序列

string fnames[]={"foo.txt", "bar.txt", "test", "a0.txt", "AAA.txt"};
//在C++中`\`会被作为字符串内的转义符,为使`\.`作为正则表达式传递进去生效,需要对`\`进行二次转义,从而有`\\.`  
std::regex txt_regex("[a-z]+\\.txt");  
for (const auto &fname: fnames)
    cout << fname << ": " << std::regex_match(fname, txt_regex) << endl;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MMb51QOd-1619770130487)(file:///C:\Users\017813~1\AppData\Local\Temp\ksohtml17320\wps15.jpg)] regex_match的另一种是依次传入string、smatch、regex三个参数。使用smatch可以方便地对匹配的结果进行获取。

string fnames[]={"foo.txt", "bar.txt", "test", "a0.txt", "AAA.txt"};
std::regex base_regex("([a-z]+)\\.txt");
std::smatch base_match;
for(const auto &fname: fnames) {  
    if (std::regex_match(fname, base_match, base_regex)) {  
    // sub_match 的第一个元素匹配整个字符串  
    // sub_match 的第二个元素匹配了第一个括号表达式    
        if (base_match.size() == 2) {      
            std::string base = base_match[1].str();  
            cout<< "sub-match[0]: " << base_match[0].str() <<endl;  
            cout << fname << " sub-match[1]: " << base << endl;    
        }  
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MyvOVnHn-1619770130489)(file:///C:\Users\017813~1\AppData\Local\Temp\ksohtml17320\wps16.jpg)] 搜索字符串成功返回1,失败返回0.默认只搜索一次,即第一个匹配

//默认只搜索一次
string seastr = "this her isres1is search! isres2is multi result test isres3is as.";
smatch srm;  //保存搜索的结果
regex rx("is(.*?)is", regex::icase);//搜索的正则式
regex_search(seastr, srm, rx);
cout << srm.str() << endl;
cout << srm[1] << endl;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TwpQ9ut1-1619770130492)(file:///C:\Users\017813~1\AppData\Local\Temp\ksohtml17320\wps17.jpg)]

查找所有匹配字符串

法一:
string seastr = "thi her isres1is search! isres2is multi result test isres3is as.";
smatch srm;  //保存搜索的结果
regex rx("is(.*?)is", regex::icase); //搜索的正则式
while (regex_search(seastr, srm, rx)) {
  cout << "--------------" << endl;
  for (auto i = 0; i < srm.size(); ++i) {
      cout << "index " << i << " : [" << srm[i] << "] \n";
  }
  seastr = srm.suffix().str();  
  //返回未端,作为新的搜索的开始,一定要设置不然死循环
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6k8tmcb1-1619770130494)(file:///C:\Users\017813~1\AppData\Local\Temp\ksohtml17320\wps18.jpg)]

法二:使用迭代器搜索所有匹配的字符串
//使用迭代器多次搜索
string seastr = "thi her isres1is search! isres2is multi result test isres3is as.";
smatch srm;  //保存搜索的结果
regex rx("is(.*?)is", regex::icase); //搜索的正则式
auto ite_begin = sregex_iterator(seastr.begin(), seastr.end(), rx);
auto ite_end = sregex_iterator();
for (sregex_iterator i = ite_begin; i != ite_end; ++i) {
  smatch mat = *i;
  cout << "--------------" << endl;
  cout << mat.str() << endl;
  cout << "index 1:" << mat[1] << endl;
}

regex_replace替换字符串,返回替换后的新字符串,后向引用用 $1,2,3,4

string str = "this is string,that is right;";
regex re("th(.*?) ", regex::icase);
string news = regex_replace(str, re, "new[$1]string");
cout << str << endl;
cout << news << endl;
//sregex_token_iterator正则分隔字符串
string str = "353this is string,that is right;";
regex sep("\\wh", regex::icase);
sregex_token_iterator endite;
sregex_token_iterator begite(str.begin(), str.end(), sep, -1);
while (begite != endite) {
  cout << *begite++ << endl;
}

sregex_iterator 迭代器适配器,调用regex_search遍历string中所有匹配的子串

smatch容器类,保存在string中搜索的结果

ssub_match string中匹配的子表达式结果

匹配结果保存

match_results<string::const_iterator> result;

smatch result; //推荐

string str = "Hello_2018";
smatch result;regex pattern("(.{5})_(\\d{4})");	
//匹配5个任意单字符+下划线+ 4个数字
if (regex_match(str, result, pattern)){
    cout << result[0] << endl; //完整匹配结果,Hello_2018
    cout << result[1] << endl; //第一组匹配的数据,Hello
    cout << result[2] << endl; //第二组匹配的数据,2018
    cout<<"结果显示形式2"<<endl;
    cout<< result.str() << endl; //完整结果,Hello_2018
    cout<< result.str(1) << endl;//第一组匹配的数据,Hello
    cout << result.str(2) << endl;//第二组匹配的数据,2018
}
for (int i = 0; i < result.size(); ++i){ //遍历结果	
    cout << result[i] << endl;
}

Search实例

string str = "255.255.12.0";
smatch result;regex pattern("\\d{1,3}"); //匹配四个数字
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;//更新搜索起始位置,搜索剩下的字符串
}

[ (img-XR7twUDR-1619770130496)(file:///C:\Users\017813~1\AppData\Local\Temp\ksohtml17320\wps19.jpg)] regex_replace 将符合匹配规则的子字符串替换为其他字符串

string str = "Hello_2018!";
regex pattern("Hello");	
cout << regex_replace(str, pattern, "") << endl; //输出:_2018,将Hello替换为""
cout<< regex_replace(str, pattern, "Hi") <<endl; //输出:Hi_2018,将Hello替换为Hi

扩展

除了直接替换以外,还有可以用来调整字符串内容(缩短、顺序等)。

string str = "Hello_2018!";	
regex pattern2("(.{3})(.{2})_(\\d{4})"); 
    //匹配3个任意字符+2个任意字符+下划线+4个数字
cout << regex_replace(str, pattern2, "$1$3") << endl;	
    //输出:Hel2018,将字符串替换为第一个和第三个表达式匹配的内容
cout << regex_replace(str, pattern2, "$1$3$2") << endl;	
    //输出:Hel2018lo,交换位置顺序

$n用于表示第n组匹配数据,所以可以利用这种方式来将字符串的内容进行调整。

匹配忽略大小写

用Regex的语法选项能够在匹配的时候忽略大小写。regex::icase:匹配时忽略大小写。

cout << regex_match("aaaAAA", regex("a*", regex::icase)) << endl;	
	//结果为1
cout << regex_match("aaaAAA", regex("a*")) << endl;		
	//结果为0