我的目标是找到文本中某些模式的所有匹配项。 让我们说我的模式是:
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"
问题:
提前致谢。
答案 0 :(得分:3)
*
贪婪 - 它会尝试匹配尽可能多的字符。您可以通过问号跟随它来使其不情愿,但更好的解决方案是,如果o
匹配的字符匹配,则从列表中排除.
,如下所示:
h[^o]*o
这是一个link对贪婪与不情愿的非常好的解释。
答案 1 :(得分:2)
除*
贪婪之外,Matches
方法只发现非重叠匹配;也就是说,它会从最后一场比赛停止的位置开始查找每个后续比赛。来自MSDN Library:
通常情况下,正则表达式引擎会开始搜索下一个匹配的确切位置。
因此,即使您使用*?
或h[^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
请注意,我已将^
和$
添加到正则表达式,以确保它与整个substring
匹配,而不仅仅是substring
的子字符串。