【问题标题】:How to get all possible matches of std::regex如何获取 std::regex 的所有可能匹配项
【发布时间】:2015-10-15 07:31:35
【问题描述】:

我想找到所有可能的正则表达式匹配,怎么可能?

regex rx("(2|25)");
string s = "2225";
for (sregex_iterator it(s.begin(), s.end(), rx), end; it != end; ++it) {
    cout << it->position() << ": " << it->str() << endl;
}

给出输出:

0: 2
1: 2
2: 25

但无法准确找到第三个2: 2。我更喜欢使用正则表达式,因为 O(n) 同时搜索多个标记的复杂性。

更新:

也许将令牌列表拆分为不可前缀列表并创建多个正则表达式?例如:(2|4|25|45|251|455|267) => (2|4), (25|45|267), (251|455) 这会将复杂度增加到类似于 O(n log(m))

更新 2:

请提供基于 STL 的将标记向量拆分为不可前缀向量的简短算法来回答此问题。

【问题讨论】:

  • 如果您只想匹配 2 上的匹配项,为什么要使用 |25 作为正则表达式的一部分?
  • @Phylogenesis 我想发现O(n) complex 的所有 4 个匹配项:)
  • 我相信你不能在两个不同的匹配组中匹配同一个字符(即你不能匹配 2 作为25 的一部分,但也不能单独匹配)。
  • @k06a 在这种情况下,为什么要使用正则表达式?这变成了一个简单的文本搜索问题。
  • 正则表达式不仅会降低算法复杂性。您必须检查每个 n 字符是否是 m 不同字符串的开头。根据您的搜索空间的性质,您将很难找到比O(nm) 工作得更好的算法(您真正希望的最好方法是进行一些预先计算以找到匹配的前缀)。

标签: c++ regex c++11 stl


【解决方案1】:

我认为使用迭代器和单个正则表达式是不可能的。这是它的工作原理。

您的正则表达式搜索“2”“25”的子字符串。现在,您使用sregex_iterator 开始搜索。它从字符串的第一个符号开始,并尝试与您的正则表达式匹配。如果有匹配,则“记录”,迭代器前进到匹配后的位置。如果没有匹配,迭代器向前推进 1 个位置。这个过程一直持续到到达字符串的末尾。

现在,每次找到匹配项时,它都会尝试从您的正则表达式中找到最佳(即最长)匹配项。因此,如果一个子字符串同时匹配225,它将需要25,因为它更长。所以我会说你需要 2 个正则表达式。

【讨论】:

  • 帮我避免m正则表达式,每个将只包含1个令牌:)复杂性增长到O(nm):(
  • 我不认为它实际上匹配最长的匹配,它匹配 first 匹配。候补的顺序很重要:请参阅example
  • @Phylogenesis,这很有意思,因为在我的机器上结果正好相反(rx1 找到 2 2 25rx2 找到 2 2 2
  • std::(basic_)regex 如果我没记错的话应该默认使用 ECMAScript 规则,这应该更喜欢第一个匹配的替代方案。如果您使用扩展/POSIX,它将更喜欢更长的 IIRC。试试这个:coliru.stacked-crooked.com/a/79388d279f74ce52
  • @k06a,如果子表达式不是任何其他子表达式的前缀,您可以将它们分组,例如您可以将3|45 分组,因为3 不是45 的前缀
【解决方案2】:

您无法获得第三个“2”,因为正则表达式总是返回最长的匹配项。为了获得“所有可能的匹配”,您需要运行两次查询,因为 2 包含在 25 中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-29
    • 1970-01-01
    • 2013-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-03
    相关资源
    最近更新 更多