PHP ereg против preg

Я заметил, что в библиотеке регулярных выражений PHP есть выбор между ereg и preg. В чем разница? Бывает один быстрее, чем другой, и если да, то почему это не медленнее?

Есть ли ситуации, когда лучше использовать один над другим?

При посещении php.net/ereg отображается следующее:

Предупреждение

Эта функция была DEPRECATED с PHP 5.3.0 и удалена с PHP 6.0.0. Опираясь на эту функцию, очень не рекомендуется.

Вниз по странице немного дальше, и мы читаем это:

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

Обратите внимание на мой акцент.

preg – библиотека Regex, совместимая с Perl
ereg – это библиотека регулярных выражений POSIX

У них немного разный синтаксис, и preg в некоторых случаях немного быстрее. ereg устарел (и он удален в php6), поэтому я бы не рекомендовал его использовать.

Существует много дискуссий о том, что происходит быстрее и лучше.

Если вы планируете когда-нибудь перейти на PHP6, ваше решение будет принято. В противном случае:

Общий консенсус в том, что PCRE – лучшее решение для всех, но если у вас есть определенная страница с большим количеством трафика, и вам не нужен PHP6, это может стоить некоторого тестирования. Например, из комментариев руководства PHP:

Устаревшее регулярное выражение POSIX в PHP для Perl-поиска похоже на замену деревянных досок и кирпича для дома с готовыми комнатами и стенами. Несомненно, вы сможете смешивать и сопоставлять некоторые части, но их намного проще модифицировать со всеми деталями, выложенными перед вами.

PCRE быстрее, чем POSIX RE? Не всегда. В недавнем проекте поисковой системы здесь, в Cynergi, у меня был простой цикл с несколькими симпатичными функциями ereg_replace (), которые занимали 3min для обработки данных. Я изменил этот 10-строчный цикл на 100-строчный рукописный код для замены, и цикл теперь занял 10 секунд для обработки одних и тех же данных! Это открыло мне глаза на то, что может В НЕКОТОРЫХ СЛУЧАЯХ быть очень медленными регулярными выражениями. В последнее время я решил изучить регулярные выражения, совместимые с Perl (PCRE). Большинство страниц утверждают, что PCRE быстрее, чем POSIX, но некоторые утверждают иначе. Я решил по своим собственным критериям. Мои первые несколько тестов подтвердили, что PCRE будет быстрее, но … результаты были немного разными, чем другие, и я решил сравнить все случаи использования RE, которые я использовал в 8000-строчном безопасном (и быстром) проекте Webmail здесь, в Cynergi, чтобы проверить это. Результаты? Неопределенный! Иногда PCRE быстрее (иногда более чем на 100 раз быстрее!), Но иногда POSIX RE быстрее (в 2 раза). Мне все еще нужно найти правило, когда они быстрее или быстрее. Речь идет не только о размере данных поиска, количестве совпадающих данных или «времени компиляции RE», который будет отображаться при частом повторении функции: всегда будет быстрее, чем другой. Но здесь я не нашел шаблона. Но, честно говоря, я также не нашел времени, чтобы изучить исходный код и проанализировать проблему. Я могу привести вам несколько примеров. POSIX RE ([0-9] {4}) / ([0-9] {2}) / ([0-9] {2}) [^ 0-9] + ([0-9] {2 }): ([0-9] {2}): ([0-9] {2}) на 30% быстрее в POSIX, чем при преобразовании в PCRE (даже если вы используете \ d и \ D и не жадное соответствие ). С другой стороны, аналогичный сложный шаблон PCRE / [0-9] {1,2} [\ t] + [a-zA-Z] {3} [\ t] + [0-9] {4} [ \ t] + [0-9] {1,2}: [0-9] {1,2} (: [0-9] {1,2})? [\ t] + [+ -] [0 -9] {4} / в PCRE в 2,5 раза быстрее, чем в POSIX RE. Простые схемы замены, такие как ereg_replace ("[^ a-zA-Z0-9 -] +", "", $ m); в POSIX RE быстрее, чем PCRE. И тогда мы снова запутались, потому что шаблон POSIX RE, подобный (^ | \ n | \ r) begin-base64 [\ t] + [0-7] {3,4} [\ t] + …… в 2 раза быстрее, чем POSIX RE, но нечувствительность к регистру PCRE / ^ Received [\ t] *: [\ t] by [\ t] + ([^ \ t] +) [\ t] / i на 30 раз быстрее, чем его версия POSIX RE! Когда дело доходит до чувствительности к регистру, PCRE до сих пор казался лучшим вариантом. Но я нашел действительно странное поведение от ereg / eregi. На очень простой POSIX RE (^ | \ r | \ n) mime-version [\ t] : я нашел eregi (), беру 3.60s (всего лишь число в тестовом тестировании), в то время как соответствующий PCRE взял 0.16s! Но если я использовал ereg () (с учетом регистра), время POSIX RE уменьшилось до 0.08s! Поэтому я исследовал дальше. Я попытался сделать сам POSIX RE нечувствительным к регистру. Я добрался до этого: (^ | \ r | \ n) [mM] [iI] [mM] [eE] -vers [iI] [oO] [nN] [\ t] *: эта версия также заняла 0.08 s. Но если я попытаюсь применить одно и то же правило к любым из букв 'v', 'e', ​​'r' или 's', которые не изменяются, время возвращается к значению 3.60s, а не постепенно, но сразу так! В данных теста не было никаких «верных» в нем, других «mime» слов в нем или любого «иона», которые могли бы ввести в заблуждение анализатор POSIX, поэтому я не понимаю. Итог: всегда проверяйте свой PCRE / POSIX RE, чтобы найти самый быстрый! Тесты выполнялись с помощью PHP 5.1.2 под Windows, из командной строки. Педро Фрейре cynergi.com

Несмотря на то, что ereg устарел в PHP 5.3, функции mb_ereg * не являются. Я считаю, что основной причиной этого является то, что PHP6 восстанавливает всю поддержку MB / Unicode, и поэтому старые «обычные» методы ereg бесполезны, так как mb_ereg будет более новым / лучшим.

Я знаю, что он не отвечает на вопрос о скорости, но это позволяет вам продолжать использовать как POSIX, так и PCRE.

Ну, ereg и его функции деривации (ereg_match и т. Д.) Устарели в php5 и удаляются в php6, поэтому вы, вероятно, лучше всего собираетесь с семейством preg.

preg для регулярных выражений в стиле Perl, а ereg – стандартное регулярное выражение POSIX.