Как преобразовать выражения ereg в preg в PHP?

140

Поскольку регулярные выражения POSIX (ereg) устарели с PHP 5.3.0, я хотел бы знать простой способ конвертировать старые выражения в PCRE (Perl-совместимые регулярные выражения) (preg) .

Например, у меня есть это регулярное выражение:

eregi('^hello world');

Как перевести выражения в preg_matchсовместимые выражения?

Примечание: этот пост служит заполнителем для всех постов, связанных с преобразованием из ereg в preg, и как дублирующие варианты для связанных вопросов. Пожалуйста, не закрывайте этот вопрос.

Связанный:

сетевой кодер
источник
2
@ yes123: Да, в том-то и дело, я тоже от этого устал. Мне нужен пост в вики, который действительно что-то объясняет, чтобы мы могли закрыть все эти отдельные вопросы.
netcoder 07
Думаю, в этом нет необходимости, потому что нужно просто обернуть старое разделителем. Также я думаю, что вы могли бы использовать для этого предыдущий ответ на вопрос.
динамический
Ах, проголосовал за закрытие, прежде чем читать комментарии. В качестве заполнителя он мог бы служить определенной цели, но разве нет другого более старого вопроса, который мог бы служить таковым?
Wrikken 07
Хм, действительно. ereg [php]не дает очень полезных результатов. Хорошо, могу поддержать это.
Wrikken 07
8
Ребята, мы, кажется, почти создали круг закрытых вопросов по этой теме, все указывающих друг на друга. В таком случае они все закроются :)
Кев,

Ответы:

142

Самое большое изменение в синтаксисе - добавление разделителей .

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 поддерживает модификаторы для разных вещей. Один из наиболее часто используемых - это модификатор без учета регистра i, альтернатива eregi :

eregi('^hello', 'HELLO');
preg_match('/^hello/i', 'HELLO');

Вы можете найти полную ссылку на синтаксис PCRE в PHP в руководстве , а также список различий между регулярным выражением POSIX и PCRE, чтобы помочь преобразовать выражение.

Однако в вашем простом примере вы не будете использовать регулярное выражение:

stripos($str, 'hello world') === 0
сетевой кодер
источник
2
Замечательное объяснение! Я хотел бы просто добавить особый случай, когда вы конвертируете из ereg в preg_match, и вам нужно экранировать только разделители, а не зарезервированные символы (поскольку они уже работали как специальные символы, мы не хотим их экранировать) : preg_match ('/'. str_replace ('/', '\ /', $ expr). '/', $ str);
Lolito 05
Особенно стоит отметить, что если вы используете совпадающие скобки, вам не нужно экранировать какие-либо символы «просто потому, что он такой же, как разделитель», как вы это делаете с другими символами, такими как /^\/hello/пример. (a(b)c)- это совершенно допустимый PCRE с разделителями. Мне лично нравится использовать круглые скобки, ()чтобы напоминать себе, что первое зафиксированное совпадение - это все.
Niet the Dark Absol
Могу я сказать, я чертовски ненавижу PHP! (.. Только что ничего другого) я должен искать ответы на эти вопросы, когда мой виртуальный хостинг сервер веба обновляется до новой версии и error_logдобудет полон эти предупреждения: PHP Deprecated: Function ereg() is deprecated in.... Ах!
c00000fd
как это преобразовать? $ regex = $ e. '((\. [^ \.'. $ e. '] [^'. $ e. '] *) | (\. \. [^'. $ e. '] +) | ([^ \. ] [^ '. $ e.'] *)) '. $ е. '\. \.' . $ e; для preg_math он выполняет свою работу, просто добавляя / modifier /
bdalina
32

Замена Ereg на preg (начиная с PHP 5.3.0) была правильным шагом в нашу пользу.

preg_match, который использует синтаксис регулярных выражений, совместимый с Perl, часто является более быстрой альтернативой ereg.

Чтобы портировать шаблоны ereg на preg, нужно знать 4 основных момента:

  1. Добавьте разделители (/):'pattern' => '/pattern/'

  2. Разделитель escape, если он является частью шаблона: 'patt/ern' => '/patt\/ern/'
    добиться его программно следующим образом:
    $old_pattern = '<div>.+</div>';
    $new_pattern = '/' . addcslashes($old_pattern, '/') . '/';

  3. eregi (сопоставление без учета регистра): 'pattern' => '/pattern/i' Итак, если вы используете функцию eregi для сопоставления без учета регистра, просто добавьте 'i' в конец нового шаблона ('/ pattern /').

  4. Значения ASCII : в ereg, если вы используете число в шаблоне, предполагается, что вы имеете в виду ASCII символа. Но в preg число не рассматривается как значение ASCII. Итак, если ваш шаблон содержит значение ASCII в выражении ereg (например: новая строка, табуляция и т. Д.), Преобразуйте его в шестнадцатеричный и префикс \ x.
    Example: 9(tab) becomes \x9 or alternatively use \t.

Сумоананд
источник
8

Начиная с версии 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

Между синтаксисом ereg()и больше различий preg_replace():

  • Возвращаемое значение:

    • При ошибке : оба возвращаютсяFALSE
    • При отсутствии совпадения : ereg()возвращается FALSE, preg_match()возвращается0
    • На матч : ereg()возвращает длину строки или 1, preg_match()возвращает всегда1
  • Результирующий массив совпадающих подстрок: Если какая-то подстрока вообще не найдена ( (b)в ...a(b)?), соответствующий элемент в ereg()результате будет FALSE, а в preg_match()нем вообще не будет установлен.

Если кто-то не достаточно храбр, чтобы преобразовать его или ее ereg()в preg_match(), он или она может использовать mb_ereg () , который все еще доступен в PHP 7.

Роман Хокке
источник