正则表达式:关于贪婪,懒惰和子串

时间:2011-03-02 05:56:25

标签: regex

我有以下字符串:

123322

理论上,正则表达式 1.*2应符合以下条件:

  • 12(因为*可以是零字符)
  • 12332
  • 123322

如果我使用正则表达式1.*2,则它与123322匹配 使用1.*?2,它将匹配12

有没有办法匹配12332

完美的事情是在字符串中获得所有可能的matchess (无论一个匹配是另一个的子串

4 个答案:

答案 0 :(得分:2)

不,除非在正则表达式中添加了其他内容以澄清它应该做什么,否则它将是贪婪的或非贪婪的。中间没有;)

答案 1 :(得分:1)

每个案例需要一个单独的表达式,具体取决于您要匹配的两个数量:

1(.*?2){1}   #same as 1.*?2
1(.*?2){2}
1(.*?2){3}
...

答案 2 :(得分:1)

通常,这是不可能的。正则表达式匹配引擎并非真正设计用于查找重叠匹配。一个快速的解决方案就是手动检查所有子串的模式:

string text = "1123322";
for (int start = 0; start < text.Length - 1; start++)
{
    for (int length = 0; length <= text.Length - start; length++)
    {
        string subString = text.Substring(start, length);
        if (Regex.IsMatch(subString, "^1.*2$"))
            Console.WriteLine("{0}-{1}: {2}", start, start + length, subString);
    }
}

工作示例:http://ideone.com/aNKnJ

现在,有可能获得一个完整的正则表达式解决方案吗?大多数情况下,答案是否定的。然而,.Net确实有一些技巧可以帮助我们:它允许可变长度的后视,并允许每个捕获组记住所有捕获(大多数引擎只返回每组的最后一个匹配)。滥用这些,我们可以在正则表达式引擎中模拟相同的for循环:

string text = "1123322!";
string allMatchesPattern = @"
(?<=^       # Starting at the local end position, look all the way to the back
(
  (?=(?<Here>1.*2\G))?  # on each position from the start until here (\G),
  .                     # *try* to match our pattern and capture it,
)*                      # but advance even if you fail to match it.
)
";

MatchCollection matches = Regex.Matches(text, allMatchesPattern,
            RegexOptions.ExplicitCapture | RegexOptions.IgnorePatternWhitespace);
foreach (Match endPosition in matches)
{
    foreach (Capture startPosition in endPosition.Groups["Here"].Captures)
    {
        Console.WriteLine("{0}-{1}: {2}", startPosition.Index,
                          endPosition.Index - 1, startPosition.Value);
    }
}

请注意,目前有一个小错误 - 引擎不会尝试匹配最后结束位置($),所以你松了几个匹配。目前,在字符串末尾添加!可以解决该问题。

工作示例:http://ideone.com/eB8Hb

答案 3 :(得分:1)

1(.*?2)*$

你将有多个捕获,你可以连接以形成所有可能的匹配

见这里:regex tester

点击“表格”并展开捕获树