Java Perl和Php中regexp实现的不同效率

Java Perl和Php中regexp实现的不同效率,java,php,regex,perl,Java,Php,Regex,Perl,在Java中: 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 $/; <> }; $s

在Java中:

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";'
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);

很久以前,我写了一个代码,下载一个网页,然后解析它以找到一个特定的值。我使用了这样的regexp,一切都很顺利

Pattern p = Pattern.compile("<tr.*?>.*?<td.*?>FOO:</td>.*?<td.*?>(.*?)</td>.*?</tr>", Pattern.DOTALL);
Matcher m = p.matcher(page);
m.find();
Pattern p=Pattern.compile(“%FOO:.*?(.*?.*”,Pattern.DOTALL);
匹配器m=p.Matcher(第页);
m、 查找();
今天网页改变了,字符串FOO不再存在,突然间m.find()不再返回,阻塞了我的整个应用程序

然后我开始调查并进行一些调试,发现对于一个普通的html页面(200kb,3000行),如果存在FOO,上面的regexp工作速度很快,否则需要几个小时

然后我说。。好吧,也许这个表达式的复杂性证明了需要等待很长时间。但是我想验证我的假设,所以我准备了一些其他语言的测试,并稍微修改了上面的模式

在我将网页保存在一个文件中并对其进行修改后,我将FOO插入了它应该位于的位置。然后我写了4个测试:

  • 将FOO与DOT_ALL匹配
  • 将条形图与点阵图全部取消匹配
  • 不带点球就不匹配FOO
  • 不带点的取消匹配条
  • 您可以在此处访问测试页面:

    在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";'
    
    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);
    
    cat page.html | perl-e'$str=do{local$/;}$str=~/.*FOO:.*(.*?).*?/s;打印“$1\n”
    cat page.html | perl-e'$str=do{local$/;}$str=~/.*条:.*(.*?).*?/s;打印“$1\n”
    cat page.html | perl-e'$str=do{local$/;}$str=~/.*FOO:.*;打印“$1\n”
    cat page.html | perl-e'$str=do{local$/;}$str=~/.*条:.*(.*?).*/;打印“$1\n”
    
    测试1、2和4立即返回。测试3需要19秒才能完成

    在PhP中:

    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";'
    
    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);
    
    preg_match('#.*?FOO:.*?(.*?.*?。#s',file#get_contents('page.html'),$vals);
    preg#u match(“#.*”栏:.*(.*?.*?。?#s”,文件获取内容('page.html'),$vals);
    preg#u match('#.*?FOO:.*?(.*?.*?)、文件获取内容('page.html')、$vals);
    preg#u match(“#.*”栏:.*(.*?.*?)”,文件获取内容('page.html'),$vals);
    
    所有4个测试都会立即返回

    在Java中,同样:

    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";'
    
    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);
    
    为了完成我的测试,我还用Java执行了测试3和测试4,它花费了数小时,就像测试2一样(但不是1,它匹配,并且执行得很快)

    这是我使用的代码(本例中为测试3):

    FileReader fr=newfilereader(“page.html”);
    char[]buff=new char[(int)new File(“page.html”).length();
    fr.read(buff);
    fr.close();
    字符串页=新字符串(浅黄色);
    Pattern p=Pattern.compile(“*?FOO:.*?(*?).*”/*,Pattern.DOTALL*/);
    匹配器m=p.Matcher(第页);
    System.out.println(m.find());
    
    结论

    PhP的性能比Perl好,也比Java好得多。为什么?
    如果php能够快速判断这个regexp是否匹配,那么为什么不在Java中移植相同的技术呢?我一直认为人类完全理解正则表达式的世界,没有其他的发现可以做。

    “我编写了一个代码,下载一个网页,然后解析它以找到一个特定的值。”。对不起,我停止在那里看书了。您应该创建一个可复制的示例来演示您的结果。难怪当有人试图用正则表达式解析HTML时,每个人都会发布一条消息。如果您从一开始就选择了HTML解析器,那么就不会有任何问题。任何带有
    *?
    的正则表达式在处理大量输入时都是注定要失败的。在我写这篇文章的时候,有三位评论员投票认为它太宽泛了。我同意它是广泛的。然而,我认为这个主题很有价值,这篇文章写得也很好,因此有理由不公开发表。@TomZych,在某种程度上我同意你的观点,但从所呈现的细节来看,这还不足以得到一个好的答案。缺少细节和许多需要解决的领域。这很有趣,也很有价值,但范围太广。1)你编写了一个糟糕的程序这一事实不是Perl错误(你有相当于8个嵌套循环),2)Perl的引擎对于失败的匹配比成功的匹配更为优化,3)Perl的引擎具有其他引擎没有的功能(需要一些速度),(4)Perl的引擎比其他引擎的bug要少得多(需要一定的速度)。