1

我的目标是找到文本中某个模式的所有匹配项。假设我的模式是:

h.*o

这意味着我正在搜索以'h'结尾开头'o'并在其间包含任意数量的字符(也为零)的任何文本。

我的理解是该方法Matches()将根据描述提供多个匹配项(请参阅MSDN)。

const string input = "hello hllo helo";
Regex regex = new Regex("h.*o");

var result = regex.Matches(input);
foreach (Match match in result)
{
    Console.WriteLine(match.Value);
}

我的期望是:

1. "hello"
2. "hllo"
3. "helo"
4. "hello hllo"
5. "hello hllo helo"

令我惊讶的是,返回的匹配只包含一个字符串——整个输入字符串。

"hello hllo helo"

问题:

  1. 哪一个是错的:我的期望,我的正则表达式或类的使用?
  2. 如何达到我的示例所示的结果?

提前致谢。

4

2 回答 2

3

*贪婪的- 它会尝试匹配尽可能多的字符。您可以通过问号来使其不情愿o,但更好的解决方案是从列表中排除.匹配的字符,如下所示:

h[^o]*o

这是一个非常好的解释贪婪与不情愿的链接。

于 2012-05-13T15:05:04.163 回答
2

*除了贪心的事实之外,该Matches方法只找到不重叠的匹配;也就是说,它会从上次匹配的位置开始查找每个后续匹配。从MSDN 库

通常,正则表达式引擎在前一个匹配停止的位置开始搜索下一个匹配。

因此,即使您使用*?orh[^o]*o代替*,它仍然只能找到“hello”、“hllo”和“helo”。

我不知道是否Regex有一个内置方法可以有效地找到与指定模式匹配的所有可能的子字符串,但是您可以自己遍历所有可能的子字符串并检查每个子字符串是否匹配:

const string input = "hello hllo helo";
Regex regex = new Regex("^h.*o$");

for (int startIndex = 0; startIndex < input.Length - 1; startIndex++)
{
    for (int endIndex = startIndex + 1; endIndex <= input.Length; endIndex++)
    {
        string substring = input.Substring(startIndex, endIndex - startIndex);
        if (regex.IsMatch(substring))
            Console.WriteLine(substring);
    }
}

输出:

hello
hello hllo
hello hllo helo
hllo
hllo helo
helo

请注意,我在正则表达式中添加了^and$以确保它匹配整个substring. 而不仅仅是substring.

于 2012-05-13T15:12:01.600 回答