Это может показаться глупым вопросом, но я долго разговаривал с некоторыми из моих коллег-разработчиков, и подумать об этом было забавно.
Так; о чем вы думаете - как выглядит регулярное выражение, которое никогда не будет сопоставлено ни одной строкой!
Изменить : почему я хочу это? Ну, во-первых, потому что мне интересно придумывать такое выражение, а во-вторых, потому что оно мне нужно для сценария.
В этом скрипте я определяю словарь как Dictionary<string, Regex>
. Как видите, он содержит строку и выражение.
На основе этого словаря я создаю методы, которые все используют этот словарь только как справочник о том, как они должны выполнять свою работу, один из них сопоставляет регулярные выражения с проанализированным файлом журнала.
Если выражение найдено, к другому Dictionary<string, long>
добавляется значение, возвращаемое выражением. Итак, чтобы поймать любые сообщения журнала, которые не соответствуют выражению в словаре, я создал новую группу под названием «unknown».
В эту группу добавляется все, что не совпало ни с чем другим. Но чтобы предотвратить несовпадение "неизвестного" -выражения (случайно) с лог-сообщением, мне пришлось создать выражение, которое наверняка никогда не будет совпадать, независимо от того, какую строку я ему задаю.
Итак, вот моя причина для этого «не настоящего вопроса» ...
источник
Ответы:
На самом деле это довольно просто,
хотя это зависит от реализации / flags*:Соответствует символу
a
после конца строки. Удачи.ВНИМАНИЕ:
это дорогое выражение - оно просканирует всю строку, найдет привязку конца строки и только после этого не найдет
a
и вернет отрицательное совпадение. (См. Комментарий ниже для более подробной информации.)* Первоначально я не особо задумывался о регулярном выражении в многострочном режиме, где
$
также соответствует конец строки. Фактически, он будет соответствовать пустой строке прямо перед новой строкой , поэтому обычный символ, например,a
никогда не может появиться после$
.источник
$a
. Его эквивалент на Perl$(?:a)
тоже очень медленныйperl -Mre=debug -e'$_=a x 50; /$(?:a)/'
.timeit
иpython3
.$a
будет соответствовать буквальному тексту$a
, поскольку$
он недопустим в качестве привязки в этом шаблоне.Кредитное плечо
negative lookahead
:этот RE является противоречивым в терминах и поэтому никогда ни с чем не будет соответствовать.
ПРИМЕЧАНИЕ.
В Python re.match () неявно добавляет якорь начала строки (
\A
) в начало регулярного выражения. Этот якорь важен для производительности: без него будет сканироваться вся строка. Те, кто не использует Python, захотят явно добавить якорь:источник
(?=x)(?!x)
и так далее (конкатенация противоречивых просмотров вперед и то же самое для просмотров назад), и многие из них также работают для произвольных значенийx
(для просмотра назад нужныx
s, которые соответствуют строкам фиксированной длины).r'a\bc'
поиск границы слова, сразу окруженной буквами с обеих сторон (вариант: символы, не являющиеся словами на обе стороны).perl -Mre=debug -e'$_=x x 8; /(?!x)x/'
. Вы можете сделать это быстрее, закрепив его в начале\A(?!x)x
или в конце(?!x)x\z
.perl -Mre=debug -e'$_=x x 8; /(?!x)x\z/; /\A(?!x)x/'
Тот, который был пропущен:
Он не может совпадать, потому что пустая строка не содержит границы слова. Протестировано на Python 2.5.
источник
\`\b\'
работает, что заменяет синтаксис Emacs на «начало / конец текста» (в отличие от «начало / конец текста»). линии").смотреть по сторонам:
(?=a)b
Для новичков в регулярных выражениях: положительный взгляд в будущее
(?=a)
гарантирует, что следующий символ естьa
, но не меняет местоположение поиска (или не включает 'a' в совпадающую строку). Теперь, когда подтверждено совпадение следующего символаa
, оставшаяся часть regex (b
) соответствует только в том случае, если это следующий символb
. Таким образом, это регулярное выражение соответствует только в том случае, если символ одновременноa
иb
одновременно.источник
a\bc
, где\b
- выражение нулевой ширины, соответствующее границе слова.Он не может появляться в середине слова, к которому мы его заставляем.
источник
a
в тексте.$.
.^
$.^
(?!)
источник
^
имеет особое значение только как первый символ регулярного выражения и$
имеет особое значение только в конце регулярного выражения, если только регулярное выражение не является многострочным выражением./$./
означает совсем другое. Это означает соответствие текущему значению$.
(номер строки ввода) . Даже/$(.)/
может совпадать с чем-то, если вы написалиuse re '/s';
перед этим. (perl -E'say "\n" =~ /$(.)/s || 0'
)^
и$
являются специальными только в начале и в конце (соответственно) шаблона, поэтому ни один из$.
или.^
или не$.^
будет работать.(?!)
я считаю, что это функция Perl / PCRE.Максимальное соответствие
По крайней мере, за одним,
a
за которым следует любое количествоa
, без возврата. Затем попробуйте сопоставить еще одинa
.или Независимое подвыражение
Это эквивалентно помещению
a+
независимого подвыражения, за которым следует другоеa
.источник
Perl 5.10 поддерживает специальные управляющие слова, называемые «глаголами», которые заключены в
(*...)
последовательность. (Сравните со(?...)
специальной последовательностью.) Среди них есть(*FAIL)
глагол, который немедленно возвращается из регулярного выражения.Обратите внимание, что глаголы также реализованы в PCRE вскоре после этого, поэтому вы можете использовать их в PHP или других языках, используя библиотеку PCRE. (Однако вы не можете использовать Python или Ruby. Они используют свой собственный движок.)
источник
\b
совпадает с границами слова - позиция между буквой и не буквой (или границей строки).\B
является его дополнением - соответствует положению между двумя буквами или между небуквами.Вместе они не могут соответствовать ни одной позиции.
Смотрите также:
источник
^\B\b
. В языках, где «начало текста» и «начало строки» имеют разный синтаксис, вы можете использовать синтаксис «начало текста», иначе вы будете тестировать каждую строку. (например, в Emacs это будет\`\B\b
или"\\`\\B\\b"
.)^
проблематично в определенном синтаксисе регулярного выражения (например, POSIX BRE), где^
привязка только тогда, когда это первый символ шаблона, а в противном случае соответствует буквальному^
символу.:)
- это непрактичный вопрос, цель которого состояла в том, чтобы найти интересный ответ, а не эффективный ответ. Тем не менее, шаблон может быть отклонен во время лайнера (с размером целевой строки), так что это неплохо для регулярного выражения - большинство шаблонов здесь одинаковы и даже^
могут быть линейными, если они не оптимизированы.Кажется, это работает:
источник
$.
. В этом случае вам придется прибегнуть к помощи$(.)
или более того$(?:.)
.$.
будет соответствовать литералу,$
за которым следует любой символ, поскольку$
он недопустим в качестве привязки в этом шаблоне.Как насчет
$^
или может быть(?!)
?источник
^
соответствует началу и$
концу строки.(?!)
- отрицательный взгляд вперед на пустую строку. Но некоторые разновидности регулярных выражений также будут рассматривать это как синтаксическую ошибку.$^
будет соответствовать этим буквальным символам, потому что символы недопустимы в качестве якорей (т.Самыми быстрыми будут:
'a' может быть любым неспециальным символом ('x', 'y'). Реализация Knio может быть немного более чистой, но эта будет быстрее для всех строк, не начинающихся с любого символа, который вы выберете вместо 'a', потому что в этих случаях он не будет соответствовать после первого символа, а не после второго.
источник
^
это особенное значение только как первый символ и аналогично с$
. С любым инструментом Unix это регулярное выражение будет соответствовать всему, что содержит буквальную строкуa^
.>^
.Python не примет это, но Perl будет:
Это регулярное выражение должно (теоретически) пытаться сопоставить бесконечное (четное) количество
w
s, потому что первая группа (()
s) рекурсивно сама в себя. Кажется, что Perl не выдает никаких предупреждений, даже если он находится нижеuse strict; use warnings;
, поэтому я предполагаю, что он, по крайней мере, действителен, и мое (минимальное) тестирование ни с чем не соответствует, поэтому я отправляю его для вашей критики.источник
perl -Mre=debug -e'"www wwww wwwww wwwwww" =~ /(w\1w)/'
[^\d\D]
или(?=a)b
илиa$a
илиa^a
источник
Это не сработает для Python и многих других языков, но в регулярном выражении Javascript
[]
это допустимый класс символов, который не может быть сопоставлен. Таким образом, следующее должно немедленно выйти из строя, независимо от того, какой ввод:Мне он нравится больше, чем
/$a/
потому, что он ясно передает свое намерение. А что касается того, когда он вам когда-нибудь понадобится, он мне понадобился, потому что мне нужен был запасной вариант для динамически скомпилированного шаблона, основанного на вводе пользователя. Когда шаблон недействителен, мне нужно заменить его шаблоном, который ничего не соответствует. В упрощенном виде это выглядит так:источник
Все примеры с использованием средства сопоставления границ следуют одному и тому же рецепту. Рецепт блюда:
Возьмите любой из граничных сопоставителей: ^, $, \ b, \ A, \ Z, \ z
Делайте противоположное тому, для чего они предназначены
Примеры:
^ и \ A предназначены для начала, поэтому не используйте их в начале
\ b соответствует границе слова, поэтому используйте его между
$, \ Z и \ z предназначены для конца, поэтому не используйте их в конце
Другие включают использование просмотра вперед и назад, которые также работают по той же аналогии: если вы даете положительный или отрицательный взгляд вперед, за которым следует что-то противоположное
Если вы положительно или отрицательно оглядываетесь назад, следуя чему-то противоположному
Их могло быть еще больше таких узоров и таких аналогий.
источник
Столько хороших ответов!
Подобно ответу @nivk, я хотел бы поделиться сравнением производительности Perl для разных вариантов никогда не совпадающего регулярного выражения.
Скорость регулярного выражения:
Скорость регулярного выражения:
(Ubuntu на Intel i5-3320M, ядро Linux 4.13, Perl 5.26)
источник
я полагаю, что
охватывает даже случаи, когда регулярное выражение включает такие флаги, как MULTILINE, DOTALL и т. д.
Я считаю (но я не тестировал его), что независимо от длины (> 0) строки между
\Z
и\A
, время до отказа должно быть постоянным.источник
или
С PCRE и PERL вы можете использовать эту команду управления возвратом, которая заставляет шаблон немедленно отказывать.
источник
Увидев некоторые из этих замечательных ответов, комментарий @arantius (относительно времени
$x
vsx^
vs(?!x)x
) на принятый в настоящее время ответ заставил меня захотеть примерить некоторые из решений, приведенных на данный момент.Используя стандарт строки 275k @ arantius, я провел следующие тесты на Python (v3.5.2, IPython 6.2.1).
TL; DR:
'x^'
и'x\by'
являются самыми быстрыми как минимум в ~ 16 раз, и, вопреки выводам @arantius,(?!x)x
были среди самых медленных (~ в 37 раз медленнее). Так что вопрос скорости, безусловно, зависит от реализации. Если скорость важна для вас, проверьте сами на своей предполагаемой системе.ОБНОВЛЕНИЕ: очевидно большое расхождение между временем
'x^'
и'a^'
. См. Этот вопрос для получения дополнительной информации и предыдущее редактирование более медленных таймингов сa
вместоx
.В первый раз, когда я запустил это, я забыл
r
использовать последние 3 выражения, поэтому это'\b'
было интерпретировано как'\x08'
символ возврата. Однако, к моему удивлению,'a\x08c'
был быстрее предыдущего результата! Честно говоря, он все равно будет соответствовать этому тексту, но я подумал, что это все же стоит отметить, потому что я не уверен, почему он быстрее.Мой тестовый файл был создан с использованием формулы «... читаемое содержимое и отсутствие повторяющихся строк» (в Ubuntu 16.04):
источник
\B\b
ужасно ошибочен с точки зрения производительности (как и любой шаблон, который не привязан к позиции, но этот шаблон особенно плох).^\B\b
Вместо этого попробуйте провести сравнительный анализ .Пустое регулярное выражение
Лучшее регулярное выражение, которое никогда ничего не соответствует, - это пустое регулярное выражение. Но я не уверен, что все движки регулярных выражений примут это.
Невозможное регулярное выражение
Другое решение - создать невозможное регулярное выражение. Я обнаружил, что
$-^
для вычисления требуется всего два шага независимо от размера вашего текста ( https://regex101.com/r/yjcs1Z/1 ).Для справки:
$^
и$.
сделайте 36 шагов для вычисления -> O (1)\b\B
занимает 1507 шагов в моем образце и увеличивается с количеством символов в вашей строке -> O (n)Более популярная ветка по этому вопросу:
источник
Может быть, это?
источник
re.compile('$.+^', re.MULTILINE|re.DOTALL).search('a\nb\nc\n')
возвращает объект соответствия, соответствующий b и c (и всем смежным и промежуточным символам новой строки). Подход с отрицательным взглядом вперед, который я рекомендую, работает (т. Е. Не соответствует чему-либо) для любой комбинации флагов, с которой он может быть скомпилирован.$
и^
./\z.+\A/
(см. Perldoc perlre ), которое предотвращает влияние многострочного и однострочного режима (use re '/ms'
).и замените ... всеми печатными символами;). Это для текстового файла.
источник
[^\x00-\xFF]+
(для байтовых реализаций).[^\s\S]
. Но, как уже сказал Фердинанд Бейер, это будет соответствовать пустой строке.*
; оставьте это значение или замените на+
, и он должен соответствовать хотя бы одному символу. Если класс исключает все возможные символы, он не может ничего сопоставить.Как насчет того, чтобы вместо регулярного выражения просто использовать оператор if всегда ложно? В javascript:
источник
Переносимое решение, которое не будет зависеть от реализации регулярного выражения, - просто использовать постоянную строку, которая, как вы уверены, никогда не появится в сообщениях журнала. Например, создайте строку на основе следующего:
Конечно, это не интеллектуальная задача, это больше похоже на программирование изоленты .
источник
Создает шаблон, содержащий только буквенно-цифровые
-
символы и ' ' (ни один из которых не является специальными символами регулярных выражений), но статистически невозможно, чтобы та же строка появлялась где-либо раньше (потому что в этом весь смысл GUID).источник