use WWW::Mechanize;
my $mech = new WWW::Mechanize;
$mech->get("http://www.elaws.gov.bw/desplaysubsidiary.php?m=SUBSIDIARY&v=I&vp=&id=904");
$page = $mech->content();
$page =~ m/.+?(\d{4})<\/i>\)/s;
当我在一些正常大小的HTML页面上运行时,上面的正则表达式很慢?为什么?我不会认为它应该运行缓慢。
编辑:这是一个演示问题的代码示例:
.+?
正则表达式线需要永远。如果我删除{{1}},则没有延迟。
答案 0 :(得分:5)
似乎对此有一些误解
假设我们有一个字符串
my $s = 'xxxxxxxxxx9999</i>)';
然后像这样的模式匹配
$s =~ m<.*?(\d{4})</i>\)>
首先假设.*?
在字符串的开头处占用无字符。然后它将检查(\d{4})</i>\)
是否与该点的字符串匹配
它失败,因此正则表达式引擎向x
提供单个字符.*?
并再次尝试。这也失败了,因此.*?
消耗的字符串部分逐字符扩展,直到匹配十个字符xxxxxxxxxx
。此时,模式的其余部分成功匹配,并且正则表达式测试被声明为成功
如果我们有非懒惰模式
$s =~ m<.*(\d{4})</i>\)>
首先假设.*
占用所有字符串
此时模式的其余部分不匹配,因此再次开始回溯,只给出.*
字符串中的一个字符并再次尝试
这和以前一样重复,但缩短匹配逐个字符,直到找到匹配字符串9999</i>)
的后九个字符并且{ {1}}现在与之前的.*
匹配
回溯 将返回转换为先前匹配的模式元素,从而更改该元素的匹配方式再试一次。它没有向后通过对象字符串寻找
这里的问题是由于xxxxxxxxxx
必须在模式中考虑。如果我们只有.*?
,那么根本就没有回溯。正则表达式引擎只搜索m<(\d{4})</i>\)>
并找到它或它不是
只要它是您想要的模式的第一个出现,这样就可以正常工作。不幸的是,找到子串的 last 出现的唯一方法是在它之前加上\d{4}</i>\)
,这将启动回溯并使进程必然更慢
当我在一些正常大小的HTML页面上运行时,上面的正则表达式很慢?
即便如此,根据您对“正常大小的HTML页面”的看法,我看不到这花费的时间超过几毫秒。正则表达式引擎用C编码,写得非常快。我想你必须在它上面运行一个计时器才能注意到任何延迟?
答案 1 :(得分:2)
这个正则表达式很慢,因为你将result = from tr in dbContext.Journals select tr;
if (!String.IsNullOrEmpty(SearchParam1)) {
result = result.Where(tr => tr.Field1.StartsWith(SearchParam1));
}
if (!String.IsNullOrEmpty(SearchParam2)) {
result = result.Where(tr => tr.Field2.StartsWith(SearchParam2));
}
与.
一起引入了懒惰。对于一个20行长的html hello world,它从60(贪婪时)到2000(懒惰时)的步骤增加。
想象一下它将如何处理&#34; 一些正常大小的HTML页面&#34;。您可以测试here(在 regex调试器下)。