C ++:如何使用正则表达式

时间:2017-07-13 02:36:28

标签: c++ regex string

我想从字符串中提取单词。我能想到的两种方法可以实现这一目标:

  1. 通过分隔符提取。
  2. 通过字模式搜索提取。
  3. 在我深入了解问题的具体细节之前,我想澄清一下,当我确实询问提取方法及其实现时,我的问题的主要焦点是正则表达式;不是实现。

    我想要匹配的单词可以包含撇号(例如“不要”),可以在双引号或单引号(撇号)内(例如“Hello”和“world”)和两者的组合(例如“没有”和“不会”)。它们还可以包含数字(例如“2017”和“U2”)和下划线和连字符(例如“hello_world”和“time-turner”)。单词撇号,下划线和连字符必须用其他单词字符包围。最后一个要求是包含随机非单词字符的字符串(例如“Goodmor¨+%g。”)仍应将所有单词字符识别为单词。

    从中提取单词的示例字符串以及我希望结果如下所示:

    1. "Hello, world!"应该会产生"Hello""world"
    2. "Aren't you clever?"应该会产生"Aren't""you""clever"
    3. "'Later', she said."应该会产生"Later""she""said"
    4. "'Maybe 5 o'clock?'"应该会产生"Maybe""5""o'clock"
    5. "In the year 2017 ..."应该会产生"In""the""year""2017"
    6. "G2g, cya l8r"应该会产生"G2g""cya""l8r"
    7. "hello_world.h"应该会产生"hello_world""h"
    8. "Hermione's time-turner."应该会产生"Hermione's""time-turner"
    9. "Good mor~+%g."应该会产生"Good""mor""g"
    10. "Hi' Testing_ Bye-"应该会产生"Hi""Testing""Bye"
    11. 因为 - 据我所知 - 我提出的两种方法需要完全不同的解决方案,我将把我的问题分成两部分 - 每种方法一个。

      1。通过分隔符提取

      这是我花费大部分时间来开发的方法,我找到了一个部分工作的解决方案 - 但是,我怀疑我使用的正则表达式不是很有效。我的解决方案就是这个(使用Boost.Regex,因为它的Perl语法支持外观):

      #include <string>
      #include <vector>
      #include <iostream>
      #include <boost/regex.hpp>
      
      
      
      std::vector<std::string> phrases({  "Hello, world!", "Aren't you clever?",
                                          "'Later', she said.", "'Maybe 5 o'clock?'",
                                          "In the year 2017 ...", "G2g, cya l8r",
                                          "hello_world.h", "Hermione's time-turner.",
                                          "Good mor~+%g.", "Hi' Testing_ Bye-"});
      std::vector<std::string> words;
      
      boost::regex delimiterPattern("^'|[\\W]*(?<=\\W)'+\\W*|(?!\\w+(?<!')'(?!')\\w+)[^\\w']+|'$");
      boost::sregex_token_iterator end;
      for (std::string phrase : phrases) {
          boost::sregex_token_iterator phraseIter(phrase.begin(), phrase.end(), delimiterPattern, -1);
      
          for ( ; phraseIter != end; phraseIter++) {
              words.push_back(*phraseIter);
              std::cout << words[words.size()-1] << std::endl;
          }
      }
      

      这个解决方案的最大问题是我的正则表达式,我觉得它看起来太复杂了,可能会做得更好。它也没有在单词结尾处正确匹配撇号 - 就像在示例3中一样。这里是regex101.com的链接,带有正则表达式和示例字符串:Delimiter regex

      2。通过文字模式搜索提取

      我没有花太多时间自己去追寻这条道路,主要是把它作为一种选择,因为我的部分解决方案不一定是最好的。关于如何实现这一点的我的建议是在重复搜索字符串以寻找模式的过程中做一些事情,在你去的时候从字符串中删除每个匹配,直到没有更多的匹配。我有一个正在使用此方法的正则表达式,但仍然希望输入:"[A-Za-z0-9]+(['_-]?[A-Za-z0-9]+)?"。以下是使用正则表达式和示例字符串regex101.com的链接:Word pattern regex

      我想再次强调,我首先要对我的正则表达式进行输入,但也非常感谢帮助实现这些方法。

      编辑:感谢@Galik指出,有些复数可以以撇号结尾。与这些相关联的撇号可以在分隔符中匹配,并且不必在单词模式中匹配(即"The kids' toys"应该导致"The""kids""toys"

1 个答案:

答案 0 :(得分:2)

您可以使用

RMSE_VersionsFile <- "RMSE_VersionsFile.RData"
if(file.exists(RMSE_VersionsFile)) {
  load(RMSE_VersionsFile)
} else {
  RMSE_Versions <- list()
}

# Do your computation

#  .
#  .
#  .
#  .

# Calculate RMSE for the models, say it is RMSE
# Give a unique version name
# For example, version with time
library(dplyr)
versionName <- Sys.time() %>% gsub(":|-| ", "_", .)
RMSE_Versions[[versionName]] <- RMSE

# lapply on RMSE_Versions, to get the mean for RMSE for all versions, as per your need
save(RMSE_Versions, file=RMSE_VersionsFile, compress=TRUE) # Only one file required

请参阅regex demo

模式详情

  • [^\W_]+(?:['_-][^\W_]+)* - 非字字符和[^\W_]+以外的一个或多个字符(匹配字母数字字符)
  • _ - 启动一个仅对子模式和匹配进行分组的非捕获组:
    • (?: - ['_-]'_
    • - - 1个字母数字字符
  • [^\W_]+ - 重复该组零次或多次。

C++ demo

)*