Intereting Posts
Как узнать, подключен ли пользователь к веб-сайту с помощью баз данных, базирующихся на php и mysql? Получить элемент в позиции N в массиве без цикла В любом случае, чтобы определить, закрывает ли пользователь браузер с помощью php? Выдать виджет (веб-приложение) с кодом активации Как получить число столбцов рабочего листа как целое (28) вместо букв Excel («AB»)? передача данных через window.location в javascript PHP вставляет несколько флажков и массивов текстовых полей в базу данных MySQL Удаление неиспользуемого CSS с кода сайта Извлечение имен функций из файла (с регулярными выражениями или без них) Ошибка анализа Неожиданный (ожидается, в php при назначении файла содержимого статическому свойству Добавление или настройка функциональности установленных пакетов file_get_contents не работает на производственном сервере, отлично работает на локальном Проблема с загрузкой файла .xlsx в PHP Преобразование <br /> в новую строку для использования в текстовой области Как хранить .pdf-файлы в MySQL как BLOB-файлы с помощью PHP?

Манипуляции строк и регулярных выражений

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

Однако, принимая во внимание накладные расходы на выполнение некоторых манипуляций с строкой ( не говоря о ошибках алгоритма), это совсем другое дело , особенно в PHP или Perl (возможно, Java ), каков предел , и в этом случае мы можем рассматривать манипуляции строк с быть лучшей альтернативой? Какие регулярные выражения особенно полезны для процессора?

Например, для следующего, на C++ , Java , PHP или Perl , что бы вы порекомендовали

Регулярные выражения, вероятно, будут быстрее:

  • s/abc/def/g или a ... while((i=index("abc",$x)>=0) ...$y .= substr()... решение?
  • s/(\d)+/N/g или алгоритм сканирования

Но что насчет

  • регулярное выражение для проверки электронной почты?
  • s/((0|\w)+?[xy]*[^xy]){2,7}/u/g

не будет ли ручной и конкретный алгоритм быстрее (пока дольше писать)?

редактировать

Вопрос заключается в том, чтобы определить, какое регулярное выражение лучше было бы переписать специально для данной проблемы с помощью манипуляции с строкой?

edit2

Общей реализацией является Perl regexp. Например, в Perl, который требует знать, как они реализованы, какого типа регулярного выражения следует избегать, потому что реализация сделает процесс длительным и неэффективным? Это может быть не сложное регулярное выражение …

июль 2011 г. (на основе комментариев)

Я не говорю, что все регулярные выражения медленны. Известно, что некоторые определенные шаблоны регулярных выражений являются медленными из-за конкретной обработки их и из-за их реализации.
Например, в недавних реализациях Perl / PHP, которые, как известно, довольно медленны, и их следует избегать?
Ответ ожидается от людей, которые уже провели собственное исследование (профилировщик …), и которые могут предоставить общие рекомендации относительно того, что рекомендуется / чего следует избегать.

Хорошей особенностью манипулирования текстом с регулярными выражениями является то, что шаблоны являются высокоуровневыми и декларативными. Это позволяет реализовать значительную возможность для оптимизации, например, факторинг самого длинного общего префикса или использование Boyer-Moore для статических строк. Краткая нотация предназначена для более быстрого чтения экспертами. Я сразу понимаю, что

 if (s/^(.)//) { ... } 

и index($_, 0, 1) = "" выглядит шумно в сравнении.

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

Кто сказал, что регулярные выражения были медленными? По крайней мере, в Perl они, как правило, являются предпочтительным методом манипулирования строками.

Regexes плохи в некоторых вещах, таких как проверка подлинности электронной почты, потому что объект слишком сложный, а не потому, что он медленный. Правильное регулярное выражение для проверки подлинности электронной почты имеет длину более 6000 символов, и оно даже не обрабатывает все случаи (сначала нужно отключить комментарии).

По крайней мере, в Perl 5, если у него есть грамматика, он, вероятно, не должен анализироваться с одним регулярным выражением.

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

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

Регулярные выражения никогда не будут быстрее, чем ручной алгоритм для очень конкретной цели. Хуже того, в PHP они должны быть скомпилированы при первом использовании (кэш используется впоследствии).

Однако они, безусловно, более кратки. Более того, написание пользовательских алгоритмов часто медленнее, чем регулярные выражения, поскольку механизм регулярных выражений обычно реализуется на языке более низкого уровня, с меньшими накладными расходами в вызывающих функциях и т. Д.

Например, preg_replace('/a/', 'b', $string) почти наверняка будет быстрее, чем цикл в PHP через строку. Но это постоянное наказание во время исполнения, а иногда регулярные выражения из-за обратного отслеживания могут иметь гораздо худшее асимптотическое поведение.

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

Некоторые регулярные выражения чрезвычайно быстрые, и разница между регулярным выражением и настраиваемым решением может быть незначительной (или не стоит никому пора беспокоиться).

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

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

Я столкнулся с этим решением в начале этого года. Фактически задача была на внешней грани того, что было возможно даже при регулярных выражениях. В конце концов я решил написать свой собственный синтаксический анализатор, встроенный автомат pushdown, который невероятно эффективен для того, что я пытался сделать. Задача, кстати, заключалась в создании чего-то, что могло бы анализировать регулярные выражения и предоставлять намеки на их использование в Intellisense.

Это несколько иронично, что я не использовал регулярные выражения для разбора регулярных выражений, но вы можете прочитать о мысли за всем этим здесь … http://blog.regexhero.net/2010/03/code-hinting-for- регулярный expressions.html

какое regexp лучше было бы переписать специально для данной проблемы с помощью строковых манипуляций?

Легко.

  1. Определите, нужно ли когда-либо переписывать что-либо.
    (положительный ответ будет примерно на 1 на 10000 скриптов, массивный синтаксический анализ текста, критический ресурс)
  2. Сделайте профиль возможным решением.
  3. Используйте один из них для данной проблемы

Что касается остальных 9999 случаев, не тратьте впустую свое время с такой мелочью и используйте то, что вам больше нравится.

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

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