Возможный дубликат:
Существует ли регулярное выражение для определения правильного регулярного выражения?
Регулярное выражение для нахождения регулярного выражения?
У меня есть приложение, которое позволяет пользователю вводить регулярное выражение. Как я могу проверить на наличие каких-либо входных данных регулярных выражений и убедиться, что они действительны, потому что, если их там нет, будут ошибки preg_match?
Я не хочу использовать «@» перед preg_match, поэтому, если есть способ проверить правильность ввода пользователем регулярных выражений, это было бы здорово.
Система регулярных выражений PHP кажется слишком сложной для меня, чтобы придумать регулярное выражение для них.
preg_match()
возвращает FALSE
если произошла ошибка.
preg_match
в пустой строке Вы можете использовать Ajax для проверки в реальном времени или проверки после отправки формы.
Вы также можете попытаться проверить, загрузив выражение в javascript regexp engine, но синтаксис js regexp не на 100% совместим с php.
Математически невозможно проверить правильное выражение, используя регулярное выражение. Это происходит потому, что (формальные) регулярные выражения могут распознавать только обычные языки . Язык – это любой набор строк. Например, набор всех десятичных чисел является языком (который, кстати, может быть описан с использованием регулярного выражения); множество всех допустимых регулярных выражений также является языком. Регулярные языки – это языки, для которых требуется только фиксированная конечная память (а не функция размера ввода).
Язык, содержащий все допустимые регулярные выражения, не является регулярным языком; следовательно, невозможно распознать регулярное выражение, используя регулярное выражение.
Чтобы понять это, обратите внимание, что регулярные выражения содержат круглые скобки в них, которые должны совпадать. Следовательно, если "(" произошло, a ")" должно произойти позже. Это невозможно описать машиной с фиксированной конечной памятью. Ибо, если бы был способ сделать это, и у вашего регулярного выражения была конечная память K различных состояний (для некоторого целого числа K), выражение с открывающимися скобками K сопровождалось скользящими круглыми скобками K, хотя действительное регулярное выражение было бы не может быть распознано этой машиной – противоречие (обратите внимание, что в формальных языках наше предположение состоит в том, что обработка текста происходит по одному символу за раз, слева направо, что является одинаковым для применяемых регулярных выражений). Мы называем такие языки, как те, которые описывают регулярные выражения, контекстно-свободные и не регулярные .
(Тривиально доказать, что регулярные выражения не образуют регулярного языка с использованием леммы о накачке )
Итак, существует фундаментальная проблема компьютерных наук в распознавании регулярных выражений с использованием регулярных выражений: математически это невозможно сделать.
Регулярные языки можно распознать автоматами конечного состояния , т.е. машины с конечными состояниями, но без памяти. Чтобы преодолеть свою проблему, вам нужно добавить некоторую память, которая зависит от размера ввода. Регулярные выражения, поскольку они не содержат контекста (к счастью, это не какой-то неясный, трудно распознаваемый тип языка), можно распознать в линейном времени с помощью пускового автомата. Это цикл «для», который проходит через выражение один токен (обычно символ) за раз и отслеживает, что он видит в стеке , то есть он «толкает» данные, которые он закрывает «всплывает» в первом мода. (Пример данных, помещенных в стек: «Мне нужно помнить, что нужно найти совпадение») «позже!»; вы можете «нажимать» это столько раз, сколько вам нужно; вы можете «постить» его позже, когда вам нужно проверить, действительно ли вам нужно было сопоставить открывающую скобку ранее).
Конечно, написание собственного механизма распознавания для регулярных выражений было бы немного накладными расходами, но если вы хотите это сделать, вы должны знать вышеуказанные ограничения. Было бы разумнее использовать уже существующий механизм для этого – я подозреваю, что вы могли бы предоставить эту работу библиотеке регулярных выражений или язык, который более увлекается обработкой регулярных выражений, таких как Perl; но @ -метод не слишком похож на идею: он может быть медленным, но ваши пользователи могут вводить ужасно медленные регулярные выражения; и это может быть плохой практикой, но в вашем случае это лучшее возможное решение.
Некоторые связанные статьи в Википедии:
Надеюсь, это помогло!
Предоставление пользователям регулярных выражений почти наверняка является плохими идеями.
Некоторые выражения очень дороги. Попробуй это:
preg_match('/(.*){1,32000}[bc]/','aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
и это всего лишь 30 символов ввода! Они не все выглядят так: /^(?:(\d+)|::)*$/
также является экспоненциальным временем в PCRE.
Первый способ, который приходит на ум, – использовать preg_last_error()
после вызова preg_match($sanatized_user_regex, "");
Если вы получаете что-то другое, кроме PREG_NO_ERROR
тогда ответьте соответствующим сообщением об ошибке.
Ваш вопрос немного неоднозначен. Вы хотите проверить «синтаксис» регулярного выражения или убедиться, что регулярное выражение фактически анализирует содержимое после применения к строке. Я думаю, что в любом случае вы должны оставить валидацию пользователю (например, предоставить отладку / текстовое поле, которое они могут ввести в строку, чтобы соответствовать их регулярному выражению. Если в регулярном выражении что-то не так, или если совпадение не найдено, ошибка «Не найдена»).
С точки зрения проверки самого регулярного выражения вы, вероятно, захотите начать с простого валидатора, который проверяет, что только действительные символы (например, часть синтаксиса регулярного выражения, такие как $, ^ \ t и т. Д.) Являются частью их регулярного выражения, но я думаю, что пытаюсь проверить логические конструкции внутри регулярного выражения могут быть довольно сложными. Возможно, есть несколько библиотек, которые проверяют синтаксис regex, но я не знаю ни о каком.