Java Perl和Php

时间:2015-11-21 22:34:02

标签: java php regex perl

在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个测试:

  1. 将FOO与DOT_ALL匹配
  2. 使用DOT_ALL
  3. 取消匹配BAR
  4. 在不使用DOT_ALL
  5. 的情况下取消匹配FOO
  6. 在不使用DOT_ALL的情况下取消匹配BAR
  7. 您可以在此处访问测试页: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中?我总是认为正则表达世界完全被人类所理解,并且没有其他发现可做。

0 个答案:

没有答案