【问题标题】:Find only first std::regex match efficiently只找到第一个 std::regex 匹配有效
【发布时间】:2019-02-06 16:38:47
【问题描述】:

我试图找到一种有效的方法来贪婪地找到std::regex 的第一个匹配项,而不分析整个输入。

我的具体问题是我编写了一个手工制作的词法分析器,并且我试图提供规则来解析常见的文字值(例如数值)。

假设一个简单的假设

std::regex integralRegex = std::regex("([+-]?[1-9]*[0-9]+)");

有没有办法从输入的开头找到最长的匹配而不扫描所有匹配?看起来std::regex_match 尝试匹配整个输入,而std::regex_search 强制查找所有匹配项。

也许我为了我的目的错过了一个微不足道的重载,但我找不到解决问题的有效方法。

只是为了澄清这个问题:我不想在第一个子匹配后停止并忽略输入的其余部分,但对于像 "51+12*3" 这样的输入,我想要找到第一个 51 匹配然后停止的东西,忽略后面的内容。

【问题讨论】:

  • 正则表达式无法匹配最长或最短匹配。您需要匹配所有匹配项,然后使用其他语言方式找到最长的匹配项。或者,在迭代时,用更长的匹配重写结果。
  • 如何在不查看整个字符串的情况下找到最长的匹配字符串?
  • 最近这里有一个类似的问题:stackoverflow.com/questions/54237547/…
  • 问题是没有找到所有出现的第一个连续匹配,这很好,问题是在像“1234 foo bar 1234 1234”这样的情况下,我想在第一个之后停止搜索一系列比赛结束(所以在第一个 1234 之后)。
  • 而 std::regex 实现并没有这样做(请参阅我发送的链接,答案是 tehre)。

标签: c++ regex c++17 lexer


【解决方案1】:

首先[+-]?[1-9]?[0-9]+ 我认为它的想法相同,但应该更快一些。或者你打算使用这样的东西:[+-]?[1-9][0-9]*|0(零没有符号或数字不以零开头)。

其次C++提供了正则表达式迭代器:

const std::string s = "51+12*3";

std::regex number_regex("[+-]?[1-9]?[0-9]+");
auto words_begin = 
    std::sregex_iterator(s.begin(), s.end(), number_regex);
auto words_end = std::sregex_iterator();

std::cout << "Found " 
          << std::distance(words_begin, words_end) 
          << " numbers:\n";

for (std::sregex_iterator i = words_begin; i != words_end; ++i) {
    std::smatch match = *i;                                                 
    std::string match_str = match.str(); 
    std::cout << match_str << '\n';
} 

看起来这就是你所需要的。

https://wandbox.org/permlink/tkaAfIslkWeY2poo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-23
    • 1970-01-01
    相关资源
    最近更新 更多