最多匹配 n 个字符

Posted

技术标签:

【中文标题】最多匹配 n 个字符【英文标题】:Match at most n characters 【发布时间】:2020-03-05 21:39:42 【问题描述】:

我正在尝试创建一个最多匹配 7 个组的正则表达式。

((X:)1,6)((:Y)1,6)

X:X:X:X:X::Y:Y             This should match
X:X:X:X:X:X::Y:Y           This should not match.

https://regex101.com/r/zxfAB7/16

有没有办法做到这一点?我需要捕获组 $1 和 $3 我正在使用 C++17 正则表达式。

【问题讨论】:

也许正则表达式是错误的工具。 你有没有让正则表达式工作(例如使用 regex101)?如果你有,那么你的 C++ 程序有什么问题?请刷新how to ask good questions,以及this question checklist。请不要忘记如何创建minimal reproducible example 向我们展示。 【参考方案1】:

如果支持正向预读,您可以使用正向预读来断言X::Y 的重复次数不是8 次。

为防止出现空匹配,您可以使用肯定的前瞻来检查是否至少有 1 个匹配。

然后使用 2 个捕获组,在第一个组中重复 0 次以上匹配 X:,在另一组中重复 0 次以上匹配 :Y

^(?=(?:X:|:Y))(?!(?:(?:X:|:Y))8)((?:X:)*)((?::Y)*)$
^ 字符串开始 (?= 正向前瞻,断言右边是 (?:X:|:Y) 匹配 X::Y )关闭正向预测 (?! 负前瞻,断言不是 8 次匹配 X::Y (?:(?:X:|:Y))8 ) 关闭负前瞻 ((?:X:)*) 捕获组 1 匹配 0+ 次 X: ((?::Y)*) 捕获组 2 匹配 0+ 次 :Y $字符串结束

Regex demo

【讨论】:

"如果支持正向前瞻,..." - 你知道支持什么。 OP 正在使用 C++17 std::regex @JesperJuhl 也许我错过了,但你在哪里看到的? 谢谢。我真的很喜欢你对正则表达式的透彻解释。【参考方案2】:

正如 Ulrich 所说,仅使用正则表达式可能不是解决方案。我会建议您以下几点:

Replace all X (occuring 1 to 6 times) by an empty string
Replace all Y (occuring 1 to 6 times) by an empty string
Use regex for determining if any X is still present
Use regex for determining if any Y is still present

如果所有XY 仅出现1 到6 次,则找不到XY(返回match),否则返回no match

【讨论】:

考虑X:X:X:X:X:X:Y:Y:Y:Y:Y:Y: 6X 和 6Y 删除它们后不再有 X 和 Y 但有 12 个,他们最多需要 7 个。【参考方案3】:

虽然已经有一个公认的答案,但我想展示一个超简单直接的解决方案。用 C++17 测试。以及完整的运行源码。

由于我们谈论的是最多 7 个组,我们可以简单地将它们全部列出并“或”它们。这可能是很多文本和复杂的 DFA。但它应该可以工作。

找到匹配后,我们定义一个向量并将所有数据/组放入其中并显示所需的结果。这很简单:

请看:

#include <iostream>
#include <string>
#include <iterator>
#include <vector>
#include <regex>

std::vector<std::string> test
    "X::Y",
    "X:X::Y",
    "X:X::Y:Y",
    "X:X:X::Y:Y",
    "X::Y:Y:Y:Y:Y",
    "X:X:X:X:X::Y:Y",
    "X:X:X:X:X:X::Y:Y"
;

const std::regex re1 R"((((X:)1,1(:Y)1,6)|((X:)1,2(:Y)1,5)|((X:)1,3(:Y)1,4)|((X:)1,4(:Y)1,3)|((X:)1,5(:Y)1,2)|((X:)1,6(:Y)1,1)))" ;
const std::regex re2 R"(((X:)|(:Y)))" ;

int main() 
    std::smatch sm;
    // Go through all test strings
    for (const std::string s : test) 
        // Look for a match
        if (std::regex_match(s, sm, re1)) 
            // Show succes message
            std::cout << "Match found for  -->  " << s << "\n";
            // Get all data (groups) into a vector
            std::vector<std::string> data std::sregex_token_iterator(s.begin(), s.end(),re2,1),  std::sregex_token_iterator() ;
            // Show desired groups
            if (data.size() >= 6) 
                std::cout << "Group 1: '" << data[0] << "'   Group 6: '" << data[5] << "'\n";
            
        
        else 
            std::cout << "**** NO match found for  -->  " << s << "\n";
        
    
    return 0;


【讨论】:

以上是关于最多匹配 n 个字符的主要内容,如果未能解决你的问题,请参考以下文章

基础正则表达式

RegEx 仅匹配数字和最多 3 个字符

正则表达式字符匹配

为什么linux进程名匹配最多只支持15个字符?

使用 awk sub 以数字方式为字符串添加前缀而不更改计数状态最多 5 个匹配“在每行具有多个匹配项的文本文件中”

ZOJ - 3265: Strange Game (优化 二分图匹配)