Что соответствует этому регулярному выражению: qr/(?!)/;
В одном исходном коде я нашел это регулярное выражение:
qr/(?!)/;
Я просто не могу понять, что это соответствует.
Честно говоря, абсолютно не понимаю, что означает отрицательное утверждение с нулевой шириной. - что я нашел в перл.: (
Может кто-нибудь объяснить это на человеческом языке, пожалуйста?:)
Ответы
Ответ 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
(?=)
, пустой положительный результат, всегда будет соответствовать. Его хакерский способ установить значение последнего успешного матча. (?!)
является его инверсным и никогда не будет соответствовать.