在Java中:
以前我写了一个代码,下载一个网页然后解析它以找到一个特定的值。我使用了这样的正则表达式,一切都很顺利。
Pattern p = Pattern.compile("<tr.*?>.*?<td.*?>FOO:</td>.*?<td.*?>(.*?)</td>.*?</tr>", Pattern.DOTALL);
Matcher m = p.matcher(page);
m.find();
今天网页发生变化,字符串FOO不再存在,突然m.find()不再返回,阻止了整个应用程序。
然后我开始调查并进行一些调试,发现使用普通的html页面(200kb,3000行),如果存在FOO,则上述正则表达式工作速度很快,否则需要数小时。
然后我说..好吧,这个表达的复杂性可能证明了等待很长时间。但是我想验证我的假设,所以我用其他语言准备了一些测试并略微修改了上述模式。
我将网页保存在一个文件中后,我对其进行了修改并插入FOO所在的位置。然后我写了4个测试:
您可以在此处访问测试页:http://pastebin.com/2S9fEpxD
在perl:
cat page.html | perl -e '$str = do { local $/; <> }; $str =~ /<tr.*?>.*?<td.*?>FOO:<\/td>.*?<td.*?>(.*?)<\/td>.*?<\/tr>/s; print "$1\n";'
cat page.html | perl -e '$str = do { local $/; <> }; $str =~ /<tr.*?>.*?<td.*?>BAR:<\/td>.*?<td.*?>(.*?)<\/td>.*?<\/tr>/s; print "$1\n";'
cat page.html | perl -e '$str = do { local $/; <> }; $str =~ /<tr.*?>.*?<td.*?>FOO:<\/td>.*?<td.*?>(.*?)<\/td>.*?<\/tr>/; print "$1\n";'
cat page.html | perl -e '$str = do { local $/; <> }; $str =~ /<tr.*?>.*?<td.*?>BAR:<\/td>.*?<td.*?>(.*?)<\/td>.*?<\/tr>/; print "$1\n";'
测试1,2和4立即返回。测试3需要19秒才能完成。
在PhP中:
preg_match( '#<tr.*?>.*?<td.*?>FOO:</td>.*?<td.*?>(.*?)</td>.*?</tr>#s',file_get_contents('page.html'), $vals);
preg_match( '#<tr.*?>.*?<td.*?>BAR:</td>.*?<td.*?>(.*?)</td>.*?</tr>#s',file_get_contents('page.html'), $vals);
preg_match( '#<tr.*?>.*?<td.*?>FOO:</td>.*?<td.*?>(.*?)</td>.*?</tr>#',file_get_contents('page.html'), $vals);
preg_match( '#<tr.*?>.*?<td.*?>BAR:</td>.*?<td.*?>(.*?)</td>.*?</tr>#',file_get_contents('page.html'), $vals);
所有4项测试立即返回。
在Java中,再次:
为了完成我的测试,我还在Java中执行了测试3和4,这需要几个小时,就像测试2(但不是1,匹配,并快速完成)
这是我使用的代码(在这种情况下为测试3):
FileReader fr = new FileReader("page.html");
char[] buff = new char[(int)new File("page.html").length()];
fr.read(buff);
fr.close();
String page = new String(buff);
Pattern p = Pattern.compile("<tr.*?>.*?<td.*?>FOO:</td>.*?<td.*?>(.*?)</td>.*?</tr>" /*, Pattern.DOTALL*/);
Matcher m = p.matcher(page);
System.out.println(m.find());
结论
PhP比Perl表现更好,并且比Java更好。为什么? 如果php能够快速判断这个正则表达式是否匹配,为什么不应该将相同的技术移植到Java中?我总是认为正则表达世界完全被人类所理解,并且没有其他发现可做。