Подтвердить что ты не робот

Что соответствует этому регулярному выражению: qr/(?!)/;

В одном исходном коде я нашел это регулярное выражение:

qr/(?!)/;

Я просто не могу понять, что это соответствует.

Честно говоря, абсолютно не понимаю, что означает отрицательное утверждение с нулевой шириной. - что я нашел в перл.: (

Может кто-нибудь объяснить это на человеческом языке, пожалуйста?:)

4b9b3361

Ответ 1

Это законно, но ничего не соответствует.

Конструкция (?!...) - это отрицательное утверждение. В деталях это означает: "соответствовать позиции, в которой следующее регулярное выражение (...) не должно соответствовать строке ввода".

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

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

Ответ 2

Пустой шаблон регулярного выражения соответствует строке нулевой длины, которая, как утверждается, всегда совпадает. Это очевидная прогрессия:

'bbbbb' =~ /^(?:aaa|bbb)/   # Matches (Matches 3 "b"s, from pos 0 to 3)
'bbbbb' =~ /^(?:aaa|bb)/    # Matches (Matches 2 "b"s, from pos 0 to 2)
'bbbbb' =~ /^(?:aaa|b)/     # Matches (Matches 1 "b",  from pos 0 to 1)
'bbbbb' =~ /^(?:aaa|)/      # Matches (Matches 0 "b"s, from pos 0 to 0)

Это означает, что (?=) ( "Является ли эта позиция следующей строкой нулевой длины?" ) всегда соответствует, а (?!) ( "Является ли эта позиция не следующей строкой нулевой длины?" ) никогда не совпадает. Фактически, (?!) оптимизируется до (*FAIL), так как последнее введение в 5.10.

(?!) aka (*FAIL) полезен для принудительного возврата назад, когда у шаблона есть побочные эффекты.

'abcd' =~ /(.+?)(?{ print "$1\n" })(?!)/;

Вывод:

a
ab
abc
abcd
b
bc
bcd
c
cd
d

Объяснение примера:

(?!) не соответствует, поэтому механизм регулярных выражений пытается найти совпадение, если .+? соответствует все больше символов. Когда это не удается, двигатель регулярных выражений пытается совместить в более позднем исходном положении.

Это называется "backtracking". Это то, как механизм регулярных выражений может соответствовать 'aaaab' =~ /a*ab/. Первый раз, a* соответствует всем 4 a s, поэтому ab не соответствует, поэтому двигатель отступает. Второй раз через a* соответствует только 3 из a s, что позволяет ab и, следовательно, весь шаблон соответствовать.

Поэтапный поток для примера я изначально дал следующее:

  • Начать сопоставление в позиции 0.
  • (.+?) соответствует a в pos 0
  • (?{ print "$1\n" }) печатает a и соответствует нулевым символам
  • (?!) не соответствует. → Возвращайтесь!
  • (.+?) соответствует ab при pos 0
  • (?{ print "$1\n" }) выводит ab и соответствует нулевым символам
  • (?!) не соответствует. → Возвращайтесь!
  • (.+?) соответствует abc при pos 0
  • (?{ print "$1\n" }) выводит abc и соответствует нулевым символам
  • (?!) не соответствует. → Возвращайтесь!
  • (.+?) соответствует abcd в pos 0
  • (?{ print "$1\n" }) печатает abcd и соответствует нулевым символам
  • (?!) не соответствует. → Возвращайтесь!
  • (.+?) не может сравниться ни с чем другим. → Возвращайтесь!
  • Начать сопоставление в позиции 1.
  • (.+?) соответствует b в pos 1
  • (?{ print "$1\n" }) выводит b и соответствует нулевым символам
  • (?!) не соответствует. → Возвращайтесь!
  • ...
  • (.+?) соответствует d в pos 3
  • (?{ print "$1\n" }) печатает d и соответствует нулевым символам
  • (?!) не соответствует. → Возвращайтесь!
  • (.+?) не может сравниться ни с чем другим. → Возвращайтесь!
  • Начать сопоставление в позиции 4.
  • (.+?) не соответствует. → Возвращайтесь!
  • Шаблон не соответствует.

Ответ 3

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