PHP 在 preg_replace 上崩溃
Posted
技术标签:
【中文标题】PHP 在 preg_replace 上崩溃【英文标题】:PHP crashes on preg_replace 【发布时间】:2013-03-14 13:04:03 【问题描述】:我使用php.exe
运行了以下脚本:
preg_replace('#(?:^[^\pL]*)|(?:[^\pL]*$)#u','',$string);
或其等价物:
preg_replace('#(?:^[^\pL]*|[^\pL]*$)#u','',$string);
如果$string="S"
或$string=" ذذ "
有效,如果string='ذ'
它产生�
不正确,如果string='ذذ'
PHP 崩溃。
但它适用于 4.4.0 - 4.4.9、5.0.5 - 5.1.6 版本。
怎么了?
见:http://3v4l.org/T3rpV
<?php
$string='دد';
echo preg_replace('#(?:^[^\pL]*)|(?:[^\pL]*$)#u','',$string);
5.4.0 - 5.5.0alpha6 的输出
Process exited with code 139.
5.2.0 - 5.3.22、5.5.0beta1 的输出
4.4.0 - 4.4.9、5.0.5 - 5.1.6 的输出
دد
4.3.11、5.0.0 - 5.0.4 的输出
Warning: preg_replace(): Compilation failed: PCRE does not support \L, \l, \N, \P, \p, \U, \u, or \X at offset 7 in /in/T3rpV on line 3
4.3.0 - 4.3.10 的输出
Warning: Compilation failed: PCRE does not support \L, \l, \N, \P, \p, \U, \u, or \X at offset 7 in /in/T3rpV on line 3
【问题讨论】:
这里也崩溃了。 PHP 5.4.7。 我可以确认,最新的 beta 版本 PHP 5.5.0beta2(3 月 28 日发布)也会崩溃! @ComFreek 我的回答是否也让它崩溃了? 【参考方案1】:您可以使用替代 mb_ereg_replace() 函数:
mb_internal_encoding("UTF-8");
mb_regex_encoding("UTF-8");
echo mb_ereg_replace('#(?:^[^\pL]*)|(?:[^\pL]*$)#u','',$string);
【讨论】:
不,你不能see it 你的正则表达式的行为完全不同,并不等同于我的。试试看:$string='.d.'
RegEx 应该重新格式化为 POSIX 语法。另外我不确定它是否支持 POSIX \pL
【参考方案2】:
也许这会有所帮助:
这些属性通常仅在 PCRE 编译时可用 "--enable-unicode-properties"
http://docs.php.net/manual/en/regexp.reference.unicode.php#96479
【讨论】:
如果这些属性不可用,PHP 会发出警告而不是崩溃。 根据我自己的经验,ive had a hard time when \b ( any word boundary character ) silently did not work with cyrillic symbols, it just ignored them, on the other hand, working as intended with latin. I had to use monster stuff like
$boundL = '(^|[-\s\.>$boundR = '($|[-\s\.><,:;\!\?]+)';跨度>
【参考方案3】:
从表达式本身来看,有两点可以改进:
*
乘数不是很有用;为什么要用空字符串替换可能为空的匹配项?事实上,在我的系统上运行它会从 preg_replace()
操作中产生 NULL
。
内存组可以合并在一起。
这是应用两项改进后的代码:
$string = 'ﺫﺫ';
var_dump(preg_replace('#(?:^[^\pL]+|[^\pL]+$)#u', '', $string));
// string(4) "ﺫﺫ"
3v4l results
如果您只是在寻找多字节修剪功能(从 4.3.0 开始支持):
$string=' دد';
var_dump(preg_replace('#(?:^\s+|\s+$)#u', '', $string));
3v4l results
【讨论】:
“事实上,在我的系统上运行它会产生 NULL”哇!实际上你发现了另一个错误:3v4l.org/H1Ihk @PHPst 看起来像 :) 我的答案中的代码有帮助吗? @Jack 它不会崩溃,但会输出string(6) "ﺫﺫ"
而不是您的预期结果。
@ComFreek 以字节为单位的长度并没有说太多,不知道为什么两个字符每个都需要 3 个字节。
@Phpst 我明白了。我会在 bugs.php.net 报告一个错误并参考这个问题。【参考方案4】:
使用preg_quote
,您必须正确转义特殊字符,然后才能将其与您的正则表达式一起使用。例如:
<?php
$string = preg_quote("\دد");
echo preg_replace('#(?:^[^\pL]*)|(?:[^\pL]*$)#u','',$string);
查看实际操作:http://3v4l.org/LeBXg
更多关于preg_quote。
干杯,
阿迪
【讨论】:
preg_quote
引用正则表达式字符,对于普通字符不是必需的。甚至echo preg_replace('#(?:^[^\pL]*|[^\pL]*$)#u','',preg_quote('ذذ'));
崩溃。 preg_quote("\دد");
是 \\ss
,这是一个不同的字符串。
可能你误解了preg_quote()
的目的,它是为了转义特殊字符以供inside正则表达式使用:)
别提了;至少我能为一位前同事做的,呵呵。
@Jack 请参考 php.net/manual/en/function.preg-quote.php 并重新阅读问题。谢谢。【参考方案5】:
终于解决了这个bug:
Output for 4.4.0 - 4.4.9, 5.0.5 - 5.1.6, 5.5.27 - 5.5.33, 5.6.11 - 7.0.4, hhvm-3.6.1 - 3.12.0 دد
【讨论】:
以上是关于PHP 在 preg_replace 上崩溃的主要内容,如果未能解决你的问题,请参考以下文章
mysql内部的preg_replace不能在循环php之外打印[重复]
preg_replace 这个:123.. - 可能是一个简单的 PHP / preg_replace / RegEx 问题,但老实说我很难过
[PHP] PHP7已经删除了preg_replace的e修饰符