C# 为什么这个正则表达式是贪婪的?
我正在尝试提取“”中包含/thumb/的所有链接。实际上我只需要使用图片src。我不知道图片是否会以jpg结尾,或者是否会有区分大小写的问题,等等。我真的只关心完整的链接C# 为什么这个正则表达式是贪婪的?,c#,regex,non-greedy,C#,Regex,Non Greedy,我正在尝试提取“”中包含/thumb/的所有链接。实际上我只需要使用图片src。我不知道图片是否会以jpg结尾,或者是否会有区分大小写的问题,等等。我真的只关心完整的链接 m = Regex.Match(page, @"""(.+?/thumbs/.+?)"""); //... var thumbUrl = m.Groups[1].Value; 我的完整代码 var page = DownloadWebPage(url); var reg = new Regex(@"Eleme
m = Regex.Match(page, @"""(.+?/thumbs/.+?)""");
//...
var thumbUrl = m.Groups[1].Value;
我的完整代码
var page = DownloadWebPage(url);
var reg = new Regex(@"Elements\s+\((.*)\)", RegexOptions.Multiline);
var m = reg.Match(page);
var szEleCount= m.Groups[1].Value;
int eleCount = int.Parse(szEleCount);
m = Regex.Match(page, @"""(.+?/thumbs/.+?)""");
while (m.Success)
{
var thumbUrl = m.Groups[1].Value;
//i break here to see a problem
m = m.NextMatch();
}
thumbUrl看起来像
中心\“>…大量文本,没有/thumbs/…src=\”问题在于?也会消耗“s”,因此它会在src属性之外继续匹配。请改用此选项:
m = Regex.Match(page, @"""([^""]+/thumbs/[^""]+)""");
Nongreedy正则表达式可能会很慢,因为引擎必须执行大量回溯 这一个只使用贪婪表达式:
@"""([^""]*/thumbs/[^""]*)"""
<>而不是匹配最少的任何东西,它匹配尽可能多的非双引号。 如果你正在解析(x)html,考虑使用适当的解析器。
请参阅:有关如何执行此操作的一些C#示例。通常,当使用正则表达式时,您使用静态字段并指定
RegexOptions。已编译的选项:
static Regex template = new Regex(@"""(.+?/thumbs/.+?)""", RegexOptions.Compiled | RegexOptions.Multiline)
不情愿(不贪婪)的方式quantifier的作用是,一旦它开始匹配,它会在第一次机会时停止。您要做的是匹配满足您的条件的最小文本量,这不是一回事;您仍然必须确保它不会在您希望匹配之前开始匹配。正如其他人所建议的,您可以通过替换+? 在正则表达式中使用与引号不匹配的内容,如[^”“]+
但这仍然会给您带来性能问题。在您的示例中,正则表达式在中心>
中看到引号时开始匹配;当它到达src=“
(假设您已将+?
更改为[^”“]+
)处的引号时,它将中止匹配的移动尝试。从src=“
中的引号开始的下一次尝试将成功。所以你现在得到了正确的结果,但是你仍然在第一次失败的比赛尝试上浪费了很多时间
编写快速正则表达式的关键是确保,如果匹配尝试失败,它会尽快失败。例如,我认为可以安全地假设您不希望在“
和/thumbs/
之间有任何尖括号,因此将它们添加到您不希望匹配的字符集中:[^”“]+
。现在,从中心“>
中的引号开始的任何匹配尝试都将在下一个位置中止
您还可以做其他事情来进一步优化正则表达式,包括原子组和负lookahead,但这可能会很快满足您的需要:
@"""([^""<>]+/thumbs/[^""<>]+)"""
@”“([^”“]+/thumbs/[^”“]+)”
FYI,“多行”选项对您没有任何帮助。如果希望点与行分隔符匹配,则应使用Singleline
。一定数量的正则表达式对象会自动缓存,因此在字段中存储一个对象不一定会对性能产生任何影响。而且,编译的
正则表达式可能更快,但创建它们的成本更高;您是否应该使用该选项取决于您如何使用正则表达式。