17

我用 PHP 编码已经有一段时间了,我一直在读到你应该只在必须使用preg_matchpreg_replace时候使用,因为它会降低性能。为什么是这样?preg_matches在一个文件中使用 20 而不是使用另一个 PHP 函数真的很糟糕吗?

4

6 回答 6

17

正如 Mike Brant 在他的回答中所说:如果需要,使用任何preg_*功能都没有错。 您想知道在一个文件中包含 20 个调用是否是个好主意,好吧,老实说:我会说这太多了。我经常说“如果您对问题的解决方案在任何给定时间都依赖于 3 个以上的正则表达式,那么您就是问题的一部分”。不过,我偶尔也会违背自己的咒语。
preg_match

如果您使用20preg_match次调用,则只需仔细查看实际的正则表达式,您就可以将这个数字减半。正则表达式,尤其是 Perl 正则表达式,非常强大,非常值得花时间去了解它们。它们趋于变慢的原因仅仅是因为必须解析正则表达式,并将其“翻译”成相当数量的低级分支和循环。a比如说,如果你想用大写字符替换所有小写字母,你可以使用正则表达式,当然,但在 PHP 中,这看起来像这样:

preg_replace('/a/','A',$string);

查看表达式,第一个参数:它是作为参数传递的字符串。该字符串将被解析(解析时,检查分隔符,创建匹配字符串然后迭代字符串,将每个字符与模式进行比较(在这种情况下a),如果子字符串匹配,则将其替换。
看起来像有点麻烦,特别是考虑到最后一步(比较子字符串和替换匹配)是我们真正想要的。

$string = str_replace('a','A',$string);

这样做,无需在解析和验证正则表达式时执行额外的检查。
不要忘记它preg_match也构造了一个匹配数组,构造一个数组也不是免费的。

简而言之:正则表达式的速度较慢,因为表达式被解析、验证并最终转换为一组简单的低级指令。

请注意,在某些情况下,人们使用explodeandimplode进行字符串操作。这也创建了一个 - 再次 - 不是免费的数组。考虑到您此后不久就会内爆相同的数组。也许另一种选择更可取(在某些情况下preg_replace 可以更快)。
基本上:正则表达式需要额外的处理,简单的字符串函数不需要。但是当有疑问时,只有一种方法可以绝对确定:设置一个测试脚本......

于 2013-01-15T17:10:17.560 回答
9

除非遇到问题,否则不要担心优化。

不要在没有使用 XDebug (http://xdebug.org) 之类的工具进行测量的情况下寻找优化区域。

如果您的代码使用 preg_match() 运行需要 100 毫秒,而通过其他方法需要 110 毫秒,那么您真的关心差异吗?

先写正确和清晰,然后考虑速度。

于 2013-01-15T16:56:44.257 回答
6

这实际上取决于您的用例。使用正则表达式本身并没有什么“坏处”。有时它是您对特定问题的唯一可用解决方案。但是,有时简单的字符串操作函数也可以正常工作。这些往往比preg*函数更快,因此,如果您遇到脚本运行非常频繁和/或要执行大量字符串操作的情况,则可以开始感受到使用正则表达式的影响。

与任何情况一样,您应该在您的应用程序和环境中进行测试并确定最适合您的方法。

于 2013-01-15T16:43:47.333 回答
4

检查它需要多少时间(显示时间STARTEDENDED):

var_dump( microtime(true) );

//...............  your function executions here.............

var_dump( microtime(true) );
于 2015-07-10T20:32:18.320 回答
3

取决于你在做什么。对于复杂的正则表达式,只需使用 preg_ 函数,如果您需要简单的替换或类似函数,请使用其他更具体的函数,如 str_replace()、strpos()、strstr()...

网络上到处都是讨论,比如http://www.simplemachines.org/community/index.php?topic=175031.0

于 2013-01-15T16:44:55.067 回答
1

对于短字符串(例如小于几千字节),性能差异可以忽略不计。对于长字符串,例如超过 30-50 kB(通常是所见即所得的内容),性能差异变得更加显着,特别是对于贪婪的变体 - 例如preg_match_all。因此,对于长字符串,使用简单的字符串迭代/查找通常会更快,例如通过str_pos()提取或替换部分字符串,substr()然后只应用 preg_* 函数 - 对于提取的短字符串。

于 2020-08-27T10:02:09.383 回答