zoukankan      html  css  js  c++  java
  • Cpp标准库之 std::regex 类的使用

    参考:https://blog.csdn.net/l357630798/article/details/78235307

    一、简介:

            本文主要是大致的介绍如何使用 C++ 标准库中 std::regex 相关类库,用来打发下无聊的时间。

            在使用 C++ 标准库正则表达式之前,肯定是要先学习正则表达式语法的,不解释。

            要学习正则表达式语法,你百度一下,可以百度一把大。但是,我个人觉得写的最经典的莫过于这篇文章了 正则表达式30分钟入门教程 ,感谢这篇文章作者 30 秒。我觉得只需要读懂这篇文章的 80%,你将感受到正则表达式处理字符串那毁天灭地的威力。


    二、常用 C++ 标准库正则表达式类:

            C++ 标准库中常用正则表达式类主要包含如下 5 组:


            有了以上 5 组模板,基本上可以处理所有的字符串处理需求了。


    三、C++ 正则表达式模板的使用:

            std::regex_match: 正则表达式需要匹配整个字符串序列,也就是说正则表达式要与字符串完全匹配。因此,它是单次匹配,否则匹配失败。

            范例代码如下:

    1.  
      void match()
    2.  
      {
    3.  
      /
    4.  
      //std::regex_match
    5.  
      //std::regex_match: 正则表达式需要匹配整个字符串序列, 也就是说正则表达式要与
    6.  
      //字符串完全匹配, 因此, 它是单次匹配, 否则匹配失败.
    7.  
      //此外, 它还可以获取子匹配的组
    8.  
       
    9.  
      std::string text = "Date:2017-10-10";
    10.  
       
    11.  
      //构造正则表达式
    12.  
      //这里 "()" 用于捕获组, 捕获组的编号是按照 "(" 出现的顺序, 从左到右, 从1开始进行编号的
    13.  
      std::string pattern = "Date.(\d{4})-(\d{2}-(\d{2}))";
    14.  
      std::regex express(pattern);
    15.  
       
    16.  
      //匹配
    17.  
      std::cout.setf(std::ios_base::boolalpha);
    18.  
      /*模板函数1-1*/
    19.  
      //第0组一般是整个正则表达式匹配结果, 其他依次是捕获组的结果
    20.  
      //这里使用的是 std::string::iterator 迭代器, 与 begin()/ end() 返回的迭代器类型(std::string::iterator)要一致
    21.  
      std::match_results<std::string::iterator> results1;
    22.  
      if(std::regex_match(text.begin(), text.end(), results1, express))
    23.  
      {
    24.  
      std::match_results<std::string::iterator>::const_iterator iter;
    25.  
      for (iter = results1.begin(); iter != results1.end(); iter++)
    26.  
      {
    27.  
      std::cout << iter->length() << ": " << iter->str() << std::endl;
    28.  
      }
    29.  
      }
    30.  
      /*输出
    31.  
      15: Date:2017-10-10
    32.  
      4: 2017
    33.  
      5: 10-10
    34.  
      2: 10
    35.  
      */
    36.  
       
    37.  
      /*模板函数1-2*/
    38.  
      //第0组一般是整个正则表达式匹配结果, 其他依次是捕获组的结果
    39.  
      //std::smatch == std::match_results<std::string::const_iterator>
    40.  
      std::smatch s_results1;
    41.  
      if(std::regex_match(text.cbegin(), text.cend(), s_results1, express))
    42.  
      {
    43.  
      std::match_results<std::string::const_iterator>::const_iterator iter;
    44.  
      for (iter = s_results1.begin(); iter != s_results1.end(); iter++)
    45.  
      {
    46.  
      std::cout << iter->length() << ": " << iter->str() << std::endl;
    47.  
      }
    48.  
      }
    49.  
      /*输出
    50.  
      15: Date:2017-10-10
    51.  
      4: 2017
    52.  
      5: 10-10
    53.  
      2: 10
    54.  
      */
    55.  
       
    56.  
      /*模板函数2*/
    57.  
      //显示字符串是否符合正则表达式, 用于检测字符串规则
    58.  
      std::cout << std::regex_match(text.begin(), text.end(), express) << std::endl;
    59.  
       
    60.  
      /*模板函数3*/
    61.  
      //第0组一般是整个正则表达式匹配结果, 其他依次是捕获组的结果
    62.  
      //std::cmatch == std::match_results<const char*>
    63.  
      std::cmatch c_results3;
    64.  
      if(std::regex_match(text.c_str(), c_results3, express))
    65.  
      {
    66.  
      for (auto iter = c_results3.begin(); iter != c_results3.end(); iter++)
    67.  
      {
    68.  
      std::cout << iter->length() << ": " << iter->str() << std::endl;
    69.  
      }
    70.  
      }
    71.  
      /*输出
    72.  
      15: Date:2017-10-10
    73.  
      4: 2017
    74.  
      5: 10-10
    75.  
      2: 10
    76.  
      */
    77.  
       
    78.  
      /*模板函数4*/
    79.  
      //显示字符串是否符合正则表达式, 用于检测字符串规则
    80.  
      std::cout << std::regex_match(text.c_str(), express) << std::endl;
    81.  
       
    82.  
      /*模板函数5*/
    83.  
      //第0组一般是整个正则表达式匹配结果, 其他依次是捕获组的结果
    84.  
      std::match_results<std::string::const_iterator> s_results5;
    85.  
      if(std::regex_match(text, s_results5, express))
    86.  
      {
    87.  
      for (size_t index = 0; index < s_results5.size(); index++)
    88.  
      {
    89.  
      //sub_match: 子匹配, match_results里面都存放的是sub_match
    90.  
      //sub_match 可以理解为 std::pair 的扩展, 它继承了 std::pair,
    91.  
      //其中 first 实际上存放的是获取的字符串头指针地址, second 为尾指针地址
    92.  
      std::ssub_match sub = s_results5[index];
    93.  
      std::cout << sub.length() << ": " << sub.str() << std::endl;
    94.  
      }
    95.  
      }
    96.  
      /*输出
    97.  
      15: Date:2017-10-10
    98.  
      4: 2017
    99.  
      5: 10-10
    100.  
      2: 10
    101.  
      */
    102.  
       
    103.  
      /*模板函数6*/
    104.  
      //显示字符串是否符合正则表达式, 用于检测字符串规则
    105.  
      std::cout << std::regex_match(text, express) << std::endl;
    106.  
      /
    107.  
      }

            std::regex_search: 搜素正则表达式参数,但它不要求整个字符序列完全匹配。而且它只进行单次搜索,搜索到即停止继续搜索,不进行重复多次搜索。

            范例代码如下:

    1.  
      void search()
    2.  
      {
    3.  
      /
    4.  
      //std::regex_search
    5.  
      //std::regex_search: 搜素正则表达式参数, 但它不要求整个字符序列完全匹配.
    6.  
      //而且它只进行单次搜索, 搜索到即停止继续搜索, 不进行重复多次搜索.
    7.  
       
    8.  
      std::string text = "Date:2017-10-10 ~ 2017-10-15";
    9.  
       
    10.  
      //构造正则表达式
    11.  
      //这里 "()" 用于捕获组, 捕获组的编号是按照 "(" 出现的顺序, 从左到右, 从1开始进行编号的
    12.  
      std::string pattern = "(\d{4})-(\d{2}-(\d{2}))";
    13.  
      std::regex express(pattern);
    14.  
       
    15.  
      //匹配
    16.  
      std::cout.setf(std::ios_base::boolalpha);
    17.  
       
    18.  
      /*模板函数1*/
    19.  
      //第0组一般是整个正则表达式匹配结果, 其他依次是捕获组的结果, 它不进行重复多次搜索
    20.  
      std::match_results<std::string::iterator> results1;
    21.  
      if(std::regex_search(text.begin(), text.end(), results1, express))
    22.  
      {
    23.  
      //使用迭代器遍历, 这里的迭代器实际上是指向 std::sub_match 的指针
    24.  
      std::match_results<std::string::iterator>::const_iterator iter;
    25.  
      for (iter = results1.begin(); iter != results1.end(); iter++)
    26.  
      {
    27.  
      std::cout << iter->length() << ": " << iter->str() << std::endl;
    28.  
      }
    29.  
      }
    30.  
      /*输出
    31.  
      10: 2017-10-10
    32.  
      4: 2017
    33.  
      5: 10-10
    34.  
      2: 10
    35.  
      */
    36.  
       
    37.  
      /*模板函数2*/
    38.  
      //显示是否有搜索到符合正则表达式的结果
    39.  
      std::cout << std::regex_search(text.begin(), text.end(), express) << std::endl;
    40.  
       
    41.  
      /*模板函数3*/
    42.  
      //第0组一般是整个正则表达式匹配结果, 其他依次是捕获组的结果, 它不进行重复多次搜索
    43.  
      std::cmatch c_results3;
    44.  
      if(std::regex_search(text.c_str(), c_results3, express))
    45.  
      {
    46.  
      for (size_t index = 0; index < c_results3.size(); index++)
    47.  
      {
    48.  
      //获取组里面的数据, 注意: 这里使用的是 std::csub_match,
    49.  
      //实际上存放在 std::match_results 里面的数据就是一组 std::sub_match
    50.  
      std::csub_match sub = c_results3[index];
    51.  
       
    52.  
      //先获取长度, 再获取内容
    53.  
      std::cout << sub.length() << ": " << sub.str() << std::endl;
    54.  
      }
    55.  
      }
    56.  
      /*输出
    57.  
      10: 2017-10-10
    58.  
      4: 2017
    59.  
      5: 10-10
    60.  
      2: 10
    61.  
      */
    62.  
       
    63.  
      /*模板函数4*/
    64.  
      //显示是否有搜索到符合正则表达式的结果
    65.  
      std::cout << std::regex_search(text.c_str(), express) << std::endl;
    66.  
       
    67.  
      /*模板函数5*/
    68.  
      //第0组一般是整个正则表达式匹配结果, 其他依次是捕获组的结果, 它不进行重复多次搜索
    69.  
      std::smatch s_results5;
    70.  
      if (std::regex_search(text, s_results5, express))
    71.  
      {
    72.  
      for (auto iter = s_results5.begin(); iter != s_results5.end(); iter++)
    73.  
      {
    74.  
      std::cout << iter->length() << ": " << iter->str() << std::endl;
    75.  
      }
    76.  
      }
    77.  
      /*输出
    78.  
      10: 2017-10-10
    79.  
      4: 2017
    80.  
      5: 10-10
    81.  
      2: 10
    82.  
      */
    83.  
       
    84.  
      /*模板函数6*/
    85.  
      //显示是否有搜索到符合正则表达式的结果
    86.  
      std::cout << std::regex_search(text, express) << std::endl;
    87.  
      }

            std::regex_replace: 多次搜索整个正则表达式(不考虑捕获组),然后替换正则表达式匹配到的结果。

            范例代码如下:

    1.  
      void replace()
    2.  
      {
    3.  
      /
    4.  
      //std::regex_replace
    5.  
      //std::regex_replace:
    6.  
       
    7.  
      std::string text = "Date:2017-10-10 ~ 2017-10-15";
    8.  
       
    9.  
      //构造正则表达式
    10.  
      //这里 "()" 用于捕获组, 捕获组的编号是按照 "(" 出现的顺序, 从左到右, 从1开始进行编号的
    11.  
      std::string pattern = "(\d{4})-(\d{2}-(\d{2}))";
    12.  
      std::regex express(pattern);
    13.  
       
    14.  
      //定义存储结果变量已经替换字符
    15.  
      std::string result(256, '0');
    16.  
      std::string substitutes = "2017-10-12";
    17.  
       
    18.  
      /*模板函数1*/
    19.  
      //多次搜索整个正则表达式(不考虑捕获组), 然后替换正则表达式匹配到的结果
    20.  
      //std::regex_replace 模板函数返回值实际上是新的字符串存入变量后尾部的指针位置, 置 0 是为了防止变量数据出错或乱码
    21.  
      *std::regex_replace(result.begin(), text.begin(), text.end(), express, substitutes) = '';
    22.  
      std::cout << result.c_str() << std::endl;
    23.  
      /*输出:
    24.  
      Date:2017-10-12 ~ 2017-10-12
    25.  
      */
    26.  
       
    27.  
      result.clear();
    28.  
      result.resize(256, '0');
    29.  
       
    30.  
      /*模板函数2*/
    31.  
      //多次搜索整个正则表达式(不考虑捕获组), 然后替换正则表达式匹配到的结果
    32.  
      //std::regex_replace 模板函数返回值实际上是新的字符串存入变量后尾部的指针位置, 置 0 是为了防止变量数据出错或乱码
    33.  
      result = std::regex_replace(text, express, substitutes);
    34.  
      std::cout << result.c_str() << std::endl;
    35.  
      /*输出:
    36.  
      Date:2017-10-12 ~ 2017-10-12
    37.  
      */
    38.  
      }

            std::regex_iterator: 用于多次重复匹配,不分组,只进行多次匹配整个正则表达式,可获取整个正则表达式的结果。

            范例代码如下:

    1.  
      void iterator()
    2.  
      {
    3.  
      /
    4.  
      //std::regex_iterator
    5.  
      //std::regex_iterator: 用于多次重复匹配, 不分组, 只进行多次匹配整个正则表达式,
    6.  
      //可获取整个正则表达式的结果
    7.  
       
    8.  
      std::string text = "Date:2017-10-10 ~ 2017-10-15";
    9.  
       
    10.  
      //构造正则表达式
    11.  
      //这里 "()" 用于捕获组, 捕获组的编号是按照 "(" 出现的顺序, 从左到右, 从1开始进行编号的
    12.  
      std::string pattern = "(\d{4})-(\d{2}-(\d{2}))";
    13.  
      std::regex express(pattern);
    14.  
       
    15.  
      std::regex_iterator<std::string::const_iterator> begin(text.cbegin(), text.cend(), express);
    16.  
      //std::sregex_iterator == std::regex_iterator<std::string::const_iterator>
    17.  
      for (auto iter = begin; iter != std::sregex_iterator(); iter++)
    18.  
      {
    19.  
      std::cout << iter->length() << ": " << iter->str() << std::endl;
    20.  
      }
    21.  
      /*输出
    22.  
      10: 2017-10-10
    23.  
      10: 2017-10-15
    24.  
      */
    25.  
      }

            std::regex_token_iterator: 用于多次匹配正则表达式, 它可以获取整个正则表达式的结果,也可以获取正则表达式的前缀,还可以获取正则表达式的分组子匹配。

            范例代码如下:

    1.  
      void token_iterator()
    2.  
      {
    3.  
      /
    4.  
      //std::regex_token_iterator
    5.  
      //std::regex_token_iterator: 用于多次匹配正则表达式, 它可以获取整个正则表达式
    6.  
      //的结果, 也可以获取正则表达式的前缀, 还可以获取正则表达式的分组子匹配
    7.  
       
    8.  
      std::string text = "Date:2017-10-10 ~ 2017-10-15";
    9.  
       
    10.  
      //构造正则表达式
    11.  
      //这里 "()" 用于捕获组, 捕获组的编号是按照 "(" 出现的顺序, 从左到右, 从1开始进行编号的
    12.  
      std::string pattern = "(\d{4})-(\d{2}-(\d{2}))";
    13.  
      std::regex express(pattern);
    14.  
       
    15.  
      /*构造函数2-1*/
    16.  
      //(多次匹配)显示正则表达式匹配, 即参数 4 等于 0
    17.  
      std::regex_token_iterator<std::string::const_iterator> begin2_1(text.cbegin(), text.cend(), express);
    18.  
      //std::sregex_token_iterator == std::regex_token_iterator<std::string::const_iterator>
    19.  
      for (auto iter = begin2_1; iter != std::sregex_token_iterator(); iter++)
    20.  
      {
    21.  
      std::cout << iter->length() << ": " << iter->str() << std::endl;
    22.  
      }
    23.  
      /*输出
    24.  
      10: 2017-10-10
    25.  
      10: 2017-10-15
    26.  
      */
    27.  
       
    28.  
      /*构造函数2-2*/
    29.  
      //(多次匹配)显示正则表达式匹配到的前缀, -1 则表示只显示前缀
    30.  
      std::regex_token_iterator<std::string::const_iterator> begin2_2(text.cbegin(), text.cend(), express, -1);
    31.  
      for (auto iter = begin2_2; iter != std::sregex_token_iterator(); iter++)
    32.  
      {
    33.  
      std::cout << iter->length() << ": " << iter->str() << std::endl;
    34.  
      }
    35.  
      /*输出
    36.  
      5: Date:
    37.  
      3: ~
    38.  
      */
    39.  
       
    40.  
      /*构造函数2-3*/
    41.  
      //(多次匹配)显示正则表达式子匹配, 3 表示第三组子匹配
    42.  
      std::regex_token_iterator<std::string::const_iterator> begin2_3(text.cbegin(), text.cend(), express, 3);
    43.  
      for (auto iter = begin2_3; iter != std::sregex_token_iterator(); iter++)
    44.  
      {
    45.  
      std::cout << iter->length() << ": " << iter->str() << std::endl;
    46.  
      }
    47.  
      /*输出
    48.  
      2: 10
    49.  
      2: 15
    50.  
      */
    51.  
       
    52.  
      /*构造函数3*/
    53.  
      //(多次匹配)显示正则表达式匹配到的前缀和子匹配, -1 表示前缀, 2 表示第二个子匹配
    54.  
      std::vector<int> vec;
    55.  
      vec.push_back(-1);
    56.  
      vec.push_back(2);
    57.  
      std::regex_token_iterator<std::string::iterator> begin3(text.begin(), text.end(), express, vec);
    58.  
      for (auto iter = begin3; iter != std::regex_token_iterator<std::string::iterator>(); iter++)
    59.  
      {
    60.  
      std::cout << iter->length() << ": " << iter->str() << std::endl;
    61.  
      }
    62.  
      /*输出
    63.  
      5: Date:
    64.  
      5: 10-10
    65.  
      3: ~
    66.  
      5: 10-15
    67.  
      */
    68.  
       
    69.  
      /*构造函数4*/
    70.  
      //(多次匹配)显示正则表达式匹配到的前缀和整个正则表达式匹配, -1 表示前缀, 0 表示匹配整个正则表达式.
    71.  
      int arr[] = {-1, 0};
    72.  
      std::regex_token_iterator<std::string::iterator> begin4(text.begin(), text.end(), express, arr);
    73.  
      for (auto iter = begin4; iter != std::regex_token_iterator<std::string::iterator>(); iter++)
    74.  
      {
    75.  
      std::cout << iter->length() << ": " << iter->str() << std::endl;
    76.  
      }
    77.  
      /*输出
    78.  
      5: Date:
    79.  
      10: 2017-10-10
    80.  
      3: ~
    81.  
      10: 2017-10-15
    82.  
      */
    83.  
      }

            主函数:
    1.  
      int main()
    2.  
      {
    3.  
      search();
    4.  
       
    5.  
      system("pause");
    6.  
      return 0;
    7.  
      }

            以上范例及说明基本上已介绍模板的使用方法,其中模板中的 match_flag_type 我没有使用,可以查阅 MSDN 来使用。另,源代码下载地址:std::regex usge demo



     
  • 相关阅读:
    Vue实现添加、删除、关键字查询
    打开新页面 自定义方法并获取携带值
    unity3d 刷新速率
    unity3d AssetStore 下载的资源位置
    unity3d c# http 请求json数据解析
    unity3d 自定义载入条/载入动画
    课程改进意见
    梦断代码
    An internal error occurred during: "Launching MVC on Tomcat 7.x".
    n以内的1的个数
  • 原文地址:https://www.cnblogs.com/kuangke/p/14702367.html
Copyright © 2011-2022 走看看