在 PHP 中编译正则表达式

Posted

技术标签:

【中文标题】在 PHP 中编译正则表达式【英文标题】:Compile regex in PHP 【发布时间】:2010-09-17 14:48:48 【问题描述】:

php 中有没有一种方法可以编译正则表达式,这样就可以在不重复编译过程的情况下将其与多个字符串进行比较?其他主要语言可以做到这一点——Java、C#、Python、javascript 等。

【问题讨论】:

【参考方案1】:

Perl 兼容的正则表达式库可能已经针对您的用例进行了优化,而无需像其他语言那样提供 Regex 类:

此扩展维护已编译正则表达式的全局每线程缓存(最多 4096 个)。

PCRE Introduction

这就是Imran 描述的研究修饰符如何在调用之间存储编译后的表达式。

【讨论】:

我可以增加每线程缓存的大小吗?4096是什么意思 我认为这意味着 4096 个已编译的正则表达式。【参考方案2】:

preg 正则表达式可以使用大写的 S(study)修饰符,这可能是您正在寻找的东西。

http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php

S

当一个模式要被多次使用时,值得花费 更多的时间来分析它,以便 加快匹配所需的时间。 如果设置了这个修饰符,那么这个 进行额外的分析。在 目前,研究模式很有用 仅适用于非锚定模式 没有一个固定的起点 字符。

【讨论】:

OP 问题的答案是不需要在 PHP 中预编译正则表达式,因为正如 1stvamp 所指出的,已编译的正则表达式会自动缓存。 'S' 修饰符是一个单独的问题。 此答案已添加到 Stack Overflow Regular Expression FAQ 的“修饰符”下。【参考方案3】:

线程是脚本当前运行的线程。第一次使用后,编译的正则表达式被缓存,下次使用PHP不再编译。

简单测试:

<?php

function microtime_float() 
    list($usec, $sec) = explode(" ", microtime());
    return ((float)$usec + (float)$sec);


// test string
$text='The big brown <b>fox</b> jumped over a lazy <b>cat</b>';
$testTimes=10;


$avg=0;
for ($x=0; $x<$testTimes; $x++)

    $start=microtime_float();
    for ($i=0; $i<10000; $i++) 
        preg_match_all('/<b>(.*)<\/b>0?/', $text, $m);
    
    $end=microtime_float();
    $avg += (float)$end-$start;


echo 'Regexp with caching avg '.($avg/$testTimes);

// regexp without caching
$avg=0;
for ($x=0; $x<$testTimes; $x++)

    $start=microtime_float();
    for ($i=0; $i<10000; $i++) 
        $pattern='/<b>(.*)<\/b>'.$i.'?/';
        preg_match_all($pattern, $text, $m);
    
    $end=microtime_float();
    $avg += (float)$end-$start;


echo '<br/>Regexp without caching avg '.($avg/$testTimes);

带有缓存 avg 0.1 的正则表达式 没有缓存的正则表达式平均 0.8

缓存正则表达式使其速度提高 8 倍!

【讨论】:

测试为 NUL!因为:您在第二个示例中连接了 3 个字符串(没有缓存),而在第一个示例中,模式中不存在“变量”$i,并且在该位置始终为0 测试仍然合理有效。通过在第一个测试中将字符串 "$j-$y" 与 $j = 37 和 $y = 5 连接,在第二个测试中连接字符串 "$i-$x"(-$x 是通过testTimes),我得到 0.0112 和 0.0431 的时间。在第二次测试中使用“$i-$y”得到相同的 0.0431,这意味着缓存的大小确实小于 10000。因此,我的实际加速比快 4 倍(不是 8 倍)。【参考方案4】:

正如另一位评论者已经说过的那样,PCRE 正则表达式已经编译,而您不必专门引用它们,PCRE 会保留一个由您提供的原始字符串索引的内部哈希。

【讨论】:

【参考方案5】:

我不肯定你可以。如果你查看Mastering Regular Expressions,一些 PHP 特定的优化技术将在第 10 章:PHP 中讨论。特别是使用 S 模式修饰符使正则表达式引擎在应用正则表达式之前对其进行“研究”。根据您的模式和文本,这可能会提高您的速度。

编辑:您可以使用books.google.com查看本书的内容。

【讨论】:

每一个使用正则表达式的开发者都应该阅读这本书!!提高效率所需的所有技术都在本书中。

以上是关于在 PHP 中编译正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

PHP正则表达式问题

PHP正则表达式如何写?

PHP正则表达式高手来啊

在Python中缓存已编译的正则表达式对象?

day19——常用正则表达式re正则对象和正则匹配效率比较编译正则对象

php 正则表达式