Boost::Regex代码示例

本文深入探讨了正则表达式在C++中的高级应用,包括使用boost库进行模式匹配、搜索、替换等操作。通过具体实例展示了如何创建、匹配、替换和分析正则表达式,涵盖了重复、贪婪、非贪婪、迭代器等功能,以及如何使用回调函数进行自定义匹配操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

看一个别人给出的例子,当我们输入“select 字符串 from 字符串”的时候,会得到输出;如果不符合这个格式,就会输出error。注意:在命令行下输入的时候,按ctrl+Z、回车表示行输入结束。
  1. #include <cstdlib>
  2. #include <stdlib.h>
  3. #include <boost/regex.hpp>
  4. #include <string>
  5. #include <iostream>
  6. using namespace std;
  7. using namespace boost;

  8. regex expression("select ([a-zA-Z]*) from ([a-zA-Z]*)");

  9. int main(int argc, char* argv[])
  10. {
  11.     std::string in;
  12.     cmatch what;
  13.     cout << "enter test string" << endl;
  14.     getline(cin,in);
  15.     if(regex_match(in.c_str(), what, expression))
  16.     {
  17.         for(int i=0;i<what.size();i++)
  18.             cout<<"str :"<<what.str()<<endl;
  19.     }
  20.     else
  21.     {
  22.         cout<<"Error Input"<<endl;
  23.     }
  24.     return 0;
  25. }

regex对象与regex_match()函数

下面是一个检测两个字符串是否符合指定表达式的例子:

  1. #include <iostream>
  2. #include <cassert>
  3. #include <string>
  4. #include <boost/regex.hpp>
  5. using namespace std;
  6. using namespace boost;
  7. int main()
  8. {
  9.     regex reg("//d{3}([a-zA-Z]+).(//d{2}|N/A)//s//1");
  10.     string correct = "123Hello N/A Hello";
  11.     string incorrect = "123Hello 12 hello";
  12.     assert(regex_match(correct,reg)==true);
  13.     assert(regex_match(incorrect,reg)==false);
  14.     return 0;
  15. }

reg的格式含义是:三个数字,1个单词,一个任意字符,2个数字或者字符串N/A,1个空格,然后再重复第一个单词。

 

下面是一个匹配邮件地址的表达式例子:

  1. #include <iostream>
  2. #include <cassert>
  3. #include <string>
  4. #include <boost/regex.hpp>
  5. using namespace std;
  6. using namespace boost;
  7. int main()
  8. {
  9.     regex reg("//w(.+)@(.+)//.com");
  10.     string correct = "boluo1982107@ccc122.com";
  11.     assert(regex_match(correct,reg)==true);
  12.     return 0;
  13. }

很有意思吧!

regex_search()函数的使用

  1. #include <iostream>
    #include <cassert>
    #include <string>
    #include <boost/regex.hpp>
    using namespace std;
    using namespace boost;
    int main()
    {
        regex reg("(new)|(delete)");
     smatch m;
        string s = "Calls to new mustbe followed by delete.  Calling simply new results in aleak!";
     int new_counter = 0;
        int delete_counter = 0;
        string::const_iterator it = s.begin();
    //    string::const_iterator end = s.end();
        while (regex_search(it,(string::const_iterator)s.end(),m,reg)) 
        {
            m[1].matched ? ++new_counter : ++delete_counter;
            it = m[0].second;
        }
        if (new_counter != delete_counter)
            cout<<"Leak detected!/n";
        else
            cout<<"Seems OK.../n";
        return 0;
    }

在上面的例子中,统计new和delete这两个单词的数目是不是一样。注意:smatch对象,它其实是一个match_results类型,分别用来记录reg中的索引是否被匹配。如果“new”被匹配了,那么m[1].matched就会为真(true);m[0].second表示it向后移动了,继续匹配剩下的字符串。

m[0],返回的是对匹配整个正则表达式的子匹配的引用,因此可以确定这个匹配的结束点通常是下次运行regex_search函数的起始点。

regex_replace()函数的使用

顾名思义,它可以用于执行文本替换。它在输入数据中进行搜索,查找正则表达式的所有匹配,对于每个匹配,该算法调用match_results::format,并将结果输出到一个传递给该函数的输出迭代器(output iterator)中。

下面的例子将英式拼法的colour替换为美式拼法的color。如果不使用正则表达式来进行这个拼写的修改,将会非常单调乏味,而且容易出错。问题在于单词中可能存在不同的大小写,而且单词可能还有很多的变形——例如colourize。为了正确地解决这个问题,需要把正则表达式分为3个子表达式:

  1. regex reg("(Colo)(u)(r)",boost::regex::icase|boost::regex::perl);

 

为了在任何匹配中能够很容易地删除字母u,我们对它进行了隔离。后面的是regex构造函数的标志参数,表示这个正则表达式不区分大小写;设置格式标志过程中的一个常见错误是忽略了regex需要默认启用的那些标志,如果没有设置这些标志,那么它们就不会启用,因此通常情况下必须使用应用应该设置的所有标志。

在使用regex_replace替换时,我们需要以参数的方式提供一个格式化字符串,该字符串决定如何进行替换。如果我们希望保留第一个和第三个匹配的子表达式,那么可以使用$N(N为子表达式的索引)来实现。下面是解决问题的完整代码:

  1. #include <iostream> 
  2. #include <cassert> 
  3. #include <string> 
  4. #include <boost/regex.hpp> 
  5. using namespace std; 
  6. using namespace boost; 
  7. int main() 
  8. {
  9.     regex reg("(Colo)(u)(r)",regex::icase | regex::perl);
  10.     string s = "Colour, colours,color,colourize";
  11.     s = regex_replace(s,reg,"$1$3");
  12. //  s = regex_replace(s,reg,"$1 wocao $3");//尝试在输出字符串中加空格   cout<<s<<endl;
  13.     return 0; 
  14. }

关于重复和贪婪

 

  1. #include <iostream> 
  2. #include <cassert> 
  3. #include <string> 
  4. #include <boost/regex.hpp> 
  5. using namespace std; 
  6. using namespace boost; 
  7. int main() 
  8. {
  9.     regex reg("(.*)(//d{2})");
  10.     cmatch m;
  11.     const char * text = "Note that I'm 31 years old, not 32.";
  12.     if (regex_search(text,m,reg))
  13.     {
  14.         if (m[1].matched)
  15.         {
  16.             cout<<m[1].str()<<'/n';
  17.         }
  18.         if (m[2].matched)
  19.         {
  20.             cout<<m[2]<<'/n';
  21.         }
  22.     }
  23. }

上面代码的输出结果是:

Note that I'm 31, not

32

也就是说,正则表达式中的".*"选项贪婪地吞掉了所有的输入!从而致使后面的子表达式无法获得匹配。按照我们的想法:31应该是符合/d{2}的条件的,应该被输出!但是可惜,它被*吞掉了。在正则表达式中,+和*都是重复性贪婪的。

为了非贪婪的重复,怎么办呢?可以在重复记号后面加一个问号"?",重复就会变成非贪婪的。修改上面代码的表达式:

  1. regex reg("(.*?)(//d{2})");

再运行程序,结果就变成:

Note that I'm

31

明白了吧?

regex_iterator的介绍和使用

 

  1. #include <iostream>  
  2. #include <cassert>  
  3. #include <string>  
  4. #include <boost/regex.hpp>  
  5. using namespace std; 
  6. using namespace boost; 
  7. class regex_callback
  8. {
  9.     int sum_;
  10. public:
  11.     regex_callback():sum_(0){}
  12.     template<typename T> void operator()(const T& what)
  13.     {
  14.         sum_+=atoi(what[1].str().c_str());
  15.     }
  16.     int sum() const
  17.     {
  18.         return sum_;
  19.     }
  20. };
  21. int main() 
  22. {
  23.     regex reg("(//d+),?");
  24.     string s = "1,1,2,3,5,8,13,21";
  25.     sregex_iterator it(s.begin(),s.end(),reg);
  26.     sregex_iterator end;

  27.     regex_callback c;
  28.     int sum = for_each(it,end,c).sum();
  29. }

sregex_iterator是regex_iterator<std::string::const_iterator>的typedef,现在的使用方法更加清晰了。我们可以对比一下前面使用regex_search的时候,不得不在循环中手动地让起始迭代器前进,而且还要手动调用regex_search函数。

regex_token_iterator的介绍和使用

它和regex_iterator相似,但是它列举的是与正则表达式不匹配的字符序列,该特性对于字符串分割非常有用。当解引用regex_token_iterator时,只有被“预订”的子表达式才可以返回。下面这个例子:输入数据的条目之间用“/”分隔,要获得两个斜杠之间的数据;使用regex_token_iterator来分隔处理就特别简单,因为它的表达式简单:regex reg("/");为了使用这个正则表达式来分割输入,需要将一个特殊的索引-1传递给regex_token_iteraotr的构造函数。

 

  1. #include <iostream>
  2. #include <cassert>
  3. #include <boost/regex.hpp>
  4. using namespace std;
  5. using namespace boost;

  6. int main()
  7. {
  8.     regex reg("/");
  9.     string s = "Split/Values/Separated/By/Slashes,";
  10.     vector<string> vec;
  11.     sregex_token_iterator it(s.begin(),s.end(),reg,-1);
  12.     sregex_token_iterator end;
  13.     while (it!=end)
  14.         vec.push_back(*it++);
  15.     assert(vec.size()==count(s.begin(),s.end(),'/')+1);
  16.     assert(vec[0]=="Split");
  17.     
  18.     return 0;
  19. }

regex_token_iterator是一个模板类,sregex_token_iterator是迭代器类型,是regex_token_iterator<std::string::const_iterator>的typedef。在上面的程序中,每次解引用返回的都是当前的sub_match,当迭代器前进时,它会尝试再次匹配该正则表达式。

 

换一个不同类型的输入,也应该能够写出程序来!

 

 

  1. #include <string>
  2. #include <iostream>
  3. #include <cassert>
  4. #include <boost/regex.hpp>
  5. using namespace std;
  6. using namespace boost;

  7. int main()
  8. {
  9.     regex reg(" ");
  10.     char* s="123 456 789 12345";
  11. //  cregex_token_iterator it;   //This is correct, too.
  12.     regex_token_iterator<char*> it(s,s+strlen(s),reg,-1);
  13.     regex_token_iterator<char*> end;
  14.     while (it!=end)
  15.     {
  16.         cout<<*it++<<endl;
  17.     }
  18.     return 0;
  19. }

当需要反复调用regex_search时,考虑使用这两个iterator,比较方便。

/A和/Z的使用

如果把/A放在正则表达式的开始,把/Z放在正则表达式的最后,那么regex_search函数的行为就可以与regex_match函数的相同——也就是说,regex_search函数必须匹配所有的输入后才能匹配成功。

下面的表达式通常要求所有的输入都能获得匹配,而不管使用regex_match还是regex_search:

  1. regex reg("//A//d*//Z");

对比regex_search和regex_match的使用:

 

  1. regex reg("//d*");
  2. bool b=regex_match("17 is prime",reg);
  3. //返回失败

  4. regex reg("//d*");
  5. bool b=regex_search("17 is prime",reg);
  6. //返回true

  7. regex reg("//d*");
  8. bool b=regex_search("17 is prime",reg);
  9. //仍然返回失败

元字符(^)的使用

元字符用来表示取反。regex reg("[^13579]");它表示一个取反的字符类,可以匹配任意非奇数的字符。

 

  1. #include <iostream>
  2. #include <cassert>
  3. #include <boost/regex.hpp>
  4. using namespace std;
  5. using namespace boost;

  6. int main()
  7. {
  8.     regex reg("[^13579]");
  9.     string s="0123456789";
  10.     sregex_iterator it(s.begin(),s.end(),reg);
  11.     sregex_iterator end;
  12.     while (it!=end)
  13.         cout<<*it++;
  14.     return 0;
  15. }

上面程序的输出结果为“02468”,如果输入字符串是“abcd”,也会全部匹配(因为它们不是奇数)。

另外,元字符^还可以用来表示一行的开始,元字符$则表示一行的结束。

无效正则表达式与异常抛出

下面这个程序还可以当作正则表达式格式输入的练习:)

 

  1. #include <string>
  2. #include <iostream>
  3. #include <cassert>
  4. #include <boost/regex.hpp>
  5. using namespace std;
  6. using namespace boost;

  7. int main()
  8. {
  9.     cout<<"Enter a regular expression:/n";
  10.     string s;
  11.     getline(cin,s);
  12.     try
  13.     {
  14.         regex reg(s);
  15.         cout<<"Now enter a string to be matched:/n";
  16.         getline(cin,s);
  17.         if (regex_match(s,reg))
  18.             cout<<"That's right!/n";
  19.         else
  20.             cout<<"No, that doesn't match!";
  21.     }
  22.     catch (bad_expression & e)
  23.     {
  24.         cout<<"That's not a valid expression! Error: "<<e.what()<<endl;
  25.     }
  26.     return 0;
  27. }

输入/d{5},输入:12345,输出:That's right!(奇怪,为什么这里输入/d而不是//d呢?输入//d没有抛出异常,却不能正确匹配!如果我输入//d,而这又是一个合法的正则表达式,那么它的匹配字符串是怎样的?)

输入错误的正则表达式:(/w*)),程序会抛出异常。

 

参考文献:超越c++标准库 Boost

<think>嗯,用户想了解Boost::regex的使用方法和示例。首先,我需要整理Boost.Regex的基本功能,比如匹配、搜索和替换。然后根据提供的引用内容,看看有没有相关的示例代码可以直接用。 引用里提到regex_match、regex_search和regex_replace这三个主要函数。比如引用2中的regex_match示例,可以用来验证字符串是否符合特定模式。用户可能需要知道怎么进行精确匹配,所以这部分应该详细说明。 接下来是regex_search,用于在字符串中查找匹配项。引用里没有直接给出示例,但根据知识,应该展示如何提取子串。比如在一个长字符串中找到符合某种格式的部分,比如邮箱或日期。 然后是regex_replace,引用3中的例子展示了替换功能,比如在数字周围加上括号。用户可能需要了解替换的语法,比如使用$&表示匹配到的内容,这部分需要解释清楚。 另外,引用4提到创建正则表达式对象和编译的问题。需要提醒用户注意正则表达式的构造和Boost库的编译设置,可能影响使用。同时,引用5提到C++11自带的正则库,如果用户环境支持的话,可能建议使用标准库,但这里还是以Boost为主。 需要检查用户的问题是否涉及更多高级用法,比如迭代器匹配或正则表达式语法,但根据提供的引用,可能不需要太深入。确保示例代码正确,并且符合用户提供的引用内容中的格式,比如正确的转义字符和语法。 最后,生成相关问题时要围绕Boost.Regex的常见问题,比如性能优化、不同函数的区别、正则语法问题等,帮助用户进一步学习。</think>### Boost::regex 使用方法及示例 #### 一、核心功能 Boost::regex 提供正则表达式操作,主要包含三个核心函数: 1. **精确匹配**:`boost::regex_match`,验证字符串是否完全符合正则表达式模式[^2] 2. **搜索匹配**:`boost::regex_search`,在字符串中查找符合模式的子串 3. **替换操作**:`boost::regex_replace`,替换匹配到的内容[^3] #### 二、基础用法示例 ##### 1. 精确匹配验证 ```cpp #include <boost/regex.hpp> #include <iostream> int main() { std::string s = "2023-12-25"; boost::regex date_pattern("\\d{4}-\\d{2}-\\d{2}"); // 日期格式验证 bool is_valid = boost::regex_match(s, date_pattern); std::cout << "Valid date: " << std::boolalpha << is_valid << std::endl; } ``` 输出:`Valid date: true` ##### 2. 内容替换 ```cpp std::string text = "Price: $99.99, Discount: $20.0"; boost::regex money_pattern("\\$\\d+\\.\\d{2}"); std::string result = boost::regex_replace(text, money_pattern, "[REDACTED]"); // 输出:Price: [REDACTED], Discount: [REDACTED][^3] ``` ##### 3. 子匹配提取 ```cpp boost::regex email_pattern("(\\w+)@(\\w+)\\.(\\w+)"); boost::smatch matches; if (boost::regex_search("contact@example.com", matches, email_pattern)) { std::cout << "Username: " << matches[1] // contact << "\nDomain: " << matches[2] // example << "\nTLD: " << matches[3] << std::endl; // com } ``` #### 三、进阶技巧 1. **迭代器匹配**:处理多个匹配项 ```cpp std::string data = "ID:A123,B456,C789"; boost::regex id_pattern("[A-Z]\\d{3}"); boost::sregex_iterator it(data.begin(), data.end(), id_pattern); boost::sregex_iterator end; while(it != end) { std::cout << "Found ID: " << it->str() << std::endl; ++it; } // 输出:A123、B456、C789 ``` 2. **正则表达式选项**:设置匹配模式 ```cpp // 忽略大小写匹配 boost::regex case_insensitive_pattern("hello", boost::regex::icase); bool match = regex_match("HELLO", case_insensitive_pattern); // true ``` #### 四、注意事项 1. **正则表达式构造**:需注意转义字符处理,例如匹配数字应写作`\\d`而非`\d`[^4] 2. **性能优化**:重复使用的正则表达式应预先编译存储 3. **兼容性**:建议优先使用C++11标准正则库(若环境支持)[^5]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值