我该如何在PHP中将ereg表达式转换为preg表达式?

152

由于自 PHP 5.3.0 起,POSIX 正则表达式 (ereg)已被弃用,我想知道将旧的表达式转换为PCRE(Perl 兼容正则表达式)(preg)的简单方法。

例如,我有这个正则表达式:

eregi('^hello world');

我该如何将表达式转换为与preg_match兼容的表达式?

注意:本帖子作为从ereg转换为preg的所有帖子的占位符,以及相关问题的重复选项。 请不要关闭此问题。

相关:


2
@yes123:是的,这就是要点,我也已经厌倦了。我希望有一个真正解释事情的维基文章,这样我们就可以关闭所有这些个别问题。 - netcoder
我认为这不必要,因为你只需要用分隔符包装旧的即可。此外,我认为你可以使用先前回答过的问题来解决这个问题。 - dynamic
啊,在看评论之前就投了关闭票。作为一个占位符,它可能有用,但是难道没有另一个更早的问题可以担当这个角色吗? - Wrikken
嗯,确实。ereg [php] 没有产生太多有用的结果。好的,我可以支持这个。 - Wrikken
@netcoder:实际上,我认为我在这里几乎回答了所有问题:http://stackoverflow.com/questions/6269693/changing-ereg-replace-to-equivalent-preg-replace/6269720#6269720 当然不是吹嘘。 - dynamic
8
各位,我们似乎已经在这个话题上创建了一个几乎彼此指向的封闭问题循环。如果继续这样下去,它们都会被关闭 :) - Kev
4个回答

152

语法中最大的变化就是添加了分隔符

ereg('^hello', $str);
preg_match('/^hello/', $str);

分隔符可以是任何非字母数字、反斜杠或空格字符。最常用的分隔符通常是~/#

您还可以使用匹配的括号:

preg_match('[^hello]', $str);
preg_match('(^hello)', $str);
preg_match('{^hello}', $str);
// etc

如果你的分隔符在正则表达式中被找到,你需要对它进行转义:

ereg('^/hello', $str);
preg_match('/^\/hello/', $str);

您可以使用preg_quote,轻松转义字符串中的所有定界符和保留字符:

$expr = preg_quote('/hello', '/');
preg_match('/^'.$expr.'/', $str);

此外,PCRE支持modifiers用于各种事情。其中最常用的是不区分大小写的修饰符i,它是eregi的替代品:
eregi('^hello', 'HELLO');
preg_match('/^hello/i', 'HELLO');

您可以在手册中找到有关PHP中PCRE语法的完整参考资料,以及POSIX正则表达式和PCRE之间的差异列表,以帮助转换表达式。

然而,在您的简单示例中,您不需要使用正则表达式:

stripos($str, 'hello world') === 0

2
非常好的解释!我想补充一个特殊情况,即当您从 ereg 转换为 preg_match 时,您只需要转义定界符而不是保留字符(因为它们已经作为特殊字符工作,我们不想转义它们):preg_match('/'.str_replace('/','/',$expr).'/', $str); - Lolito
1
值得注意的是,如果您使用匹配括号,则不需要像处理其他符号(例如/^\/hello/)那样转义任何字符“只是因为它与定界符相同”。(a(b)c)是一个完全有效的定界PCRE。我个人喜欢使用括号(),以便提醒自己第一个捕获的匹配是整个内容。 - Niet the Dark Absol
如何转换这个代码?$regex = $e . '((.[^.' . $e . '][^' . $e . '])|(..[^' . $e . ']+)|([^.][^' . $e . ']))' . $e . '..' . $e; 为了preg_match,不能只添加/modifier/。 - bdalina

36

将 ereg 替换为 preg(PHP 5.3.0 版本及以上)是对我们有利的正确举措。

使用 Perl 兼容正则表达式语法的 preg_match 通常比 ereg 更快。

转换 ereg 模式为 preg 需要注意以下四点:

  1. 添加定界符(/): 'pattern' => '/pattern/'

  2. 如果分隔符是模式的一部分,请进行分隔符转义'patt/ern' => '/patt\/ern/'
    以以下方式自动实现:
    $old_pattern = '<div>.+</div>';
    $new_pattern = '/' . addcslashes($old_pattern, '/') . '/';

  3. eregi(不区分大小写匹配): 'pattern' => '/pattern/i' 因此,如果您正在使用 eregi 函数进行不区分大小写匹配,请在新模式('/pattern/')末尾添加 'i'。

  4. ASCII 值:在 ereg 中,如果您在模式中使用数字,则默认为字符的 ASCII。但在 preg 中,数字不被视为 ASCII 值。因此,如果您的模式包含 ereg 表达式中的 ASCII 值(例如:换行符、制表符等),则将其转换为十六进制并在前面加上 \x。
    例如:9(制表符)变成 \x9 或使用 \t。


12

从PHP 5.3版本开始,ereg已被弃用。

ereg转换至preg_match只需要在模式中进行小的更改。

首先,您需要向您的代码添加定界符,例如:

ereg('A-Z0-9a-z', 'string');
preg_match('/A-Z0-9a-z/', 'string');

对于不区分大小写的eregi匹配,将i放在最后一个定界符之后,例如:

eregi('pattern', 'string');

对于

preg_match ('/pattern/i', 'string');

7
< p > ereg() preg_replace() 之间的差异不仅在语法上,还有更多的区别:

  • 返回值:

    • 出现错误:两者都返回FALSE
    • 未匹配到ereg() 返回FALSEpreg_match() 返回0
    • 匹配成功ereg() 返回字符串长度或1preg_match() 总是返回1
  • 匹配子字符串的结果数组:如果某个子字符串根本没有被找到(在...a(b)?中的(b)),则ereg()结果中相应的项将为FALSE,而在preg_match()中将根本不设置。

如果一个人不敢将他或她的ereg()转换为preg_match(),他或她可以使用mb_ereg(),它仍然可用于PHP 7。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接