Почему это регулярное выражение занимает так много времени, чтобы найти адреса электронной почты в определенных файлах? - PullRequest
6 голосов
/ 18 ноября 2011

У меня есть регулярное выражение, которое ищет адреса электронной почты (это было взято из другого SO сообщения, которое я не могу найти, и было проверено на всех видах конфигураций электронной почты ... изменить это не совсем мой вопрос ... но поймите, если это является основной причиной):

/[a-z0-9_\-\+]+@[a-z0-9\-]+\.([a-z]{2,3})(?:\.[a-z]{2})?/i

Я использую preg_match_all () в PHP.

Это прекрасно работает для 99,99% файлов, которые я просматриваю, и занимает около 5 мс, но иногда занимает пару минут. Эти файлы больше, чем средняя веб-страница, размером около 300 Кб, но гораздо большие файлы обычно обрабатываются нормально Единственное, что я могу найти в содержимом файла, которое выделяется, это строки из тысяч последовательных «случайных» буквенно-цифровых символов, таких как:

wEPDwUKMTk0ODI3Nzk5MQ9kFgICAw9kFgYCAQ8WAh4H...

Вот две страницы, вызывающие проблему. Просмотр источника, чтобы увидеть длинные строки.

Есть мысли о том, что вызывает это?

- ЗАКЛЮЧИТЕЛЬНОЕ РЕШЕНИЕ -

Я проверил различные регулярные выражения, предложенные в ответах. Ответ @ FailedDev помог и сократил время обработки с нескольких минут до нескольких секунд. Ответ @ hakre решил проблему и сократил время обработки до нескольких сотен миллисекунд. Ниже приведено последнее регулярное выражение, которое я использовал. Это второе предложение @ hakre.

/[a-z0-9_\-\+]{1,256}+@[a-z0-9\-]{1,256}+\.([a-z]{2,3})(?:\.[a-z]{2})?/i

Ответы [ 2 ]

8 голосов
/ 18 ноября 2011

Вы уже знаете, что ваше регулярное выражение вызывает проблему для больших файлов.Так, может быть, вы можете сделать это немного умнее?

Например, вы используете + для соответствия одному или нескольким символам.Допустим, у вас есть строка из 10 000 символов.Регулярное выражение должно искать 10 000 комбинаций, чтобы найти наибольшее совпадение.Затем вы объединяете это с похожими.Допустим, у вас есть строка с 20 000 символов и две группы +.Как они могут совпадать в файле.Вероятно, 10 000 х 10 000 возможностей.И т. Д. И т. П.

Если вы можете ограничить количество символов (похоже, вы ищете шаблоны электронной почты), возможно, ограничьте доменное имя адреса электронной почты до 256, а сам адрес -256 символов.Тогда это будет 256 x 256 возможностей для проверки «только»:

/[a-z0-9_\-\+]{1,256}@[a-z0-9\-]{1,256}\.([a-z]{2,3})(?:\.[a-z]{2})?/i

Это, вероятно, уже намного быстрее.Тогда сделав эти квантификаторы притяжательными, вы уменьшите количество возвратов для PCRE:

/[a-z0-9_\-\+]{1,256}+@[a-z0-9\-]{1,256}+\.([a-z]{2,3})(?:\.[a-z]{2})?/i

Что должно ускорить его снова.

6 голосов
/ 18 ноября 2011

Мое лучшее предположение было бы попробовать использовать позитивные квантификаторы:

[a-z0-9_\-\+]+

до

[a-z0-9_\-\+]++

Это должно привести к сбою регулярного выражения быстрее, что может улучшить производительность в этих ситуациях.

Edit:

Может быть атомная группировка также может помочь:

/(?>[a-z0-9_\-+]++)@(?>[a-z0-9\-]++\.)(?>[a-z]{2,3})(?:\.[a-z]{2})?/

Сначала вы должны выбрать первый вариант. Было бы интересно узнать, есть ли разница, также используя второй вариант.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...