В чем разница между?:,?! и? = в регулярном выражении?
Я искал значение этих выражений, но не мог понять точного различия между ними.
Это то, что они говорят:
-
?:
Сопоставить выражение, но не записывать его.
-
?=
Сопоставьте суффикс, но исключите его из захвата.
-
?!
Соответствует, если суффикс отсутствует.
Я попытался использовать их в простой RegEx и получил похожие результаты для всех.
Пример: следующие 3 выражения дают очень похожие результаты.
Ответы
Ответ 1
Разница между ?=
и ?!
заключается в том, что первое требует, чтобы данное выражение соответствовало, а второе требовало соответствия не. Например, a(?=b)
будет соответствовать "a" в "ab", но не "a" в "ac". В то время как a(?!b)
будет соответствовать "a" в "ac", но не "a" в "ab".
Разница между ?:
и ?=
заключается в том, что ?=
исключает выражение из всего соответствия, а ?:
просто не создает группу захвата. Так, например, a(?:b)
будет соответствовать "ab" в "abc" , а a(?=b)
будет соответствовать только "a" в "abc" . a(b)
будет соответствовать "ab" в "abc" и создать захват, содержащий "b".
Ответ 2
?: is for non capturing group
?= is for positive look ahead
?! is for negative look ahead
?<= is for positive look behind
?<! is for negative look behind
Пожалуйста, проверьте здесь: http://www.regular-expressions.info/lookaround.html за очень хороший учебник и примеры в lookahead в регулярных выражениях.
Ответ 3
Чтобы лучше понять, примените три выражения плюс группу захвата и проанализируйте каждое поведение.
-
()
группа захвата - регулярное выражение внутри скобки должно быть сопоставлено и совпадение создает группу захвата
-
(?:)
не захватывающая группа - регулярное выражение внутри скобки должно быть сопоставлено, но не создает группу захвата
-
(?=)
позитивный взгляд вперед - утверждает, что регулярное выражение должно быть сопоставлено
-
(?!)
негативный взгляд вперед - утверждает, что невозможно совместить регулярное выражение
Пусть применяется q(u)i
для выхода. q
соответствует q, а группа захвата u
соответствует u. Выполняется совпадение внутри группы захвата и создается группа захвата. Таким образом, двигатель продолжает работать с i
. И i
будет соответствовать i. Эта последняя попытка матча успешна. qui, и создается группа захвата с u.
Пусть применяется q(?:u)i
для выхода. Опять же, q
соответствует q, а группа non-capture u
соответствует u. Выполняется совпадение от группы, не связанной с захватом, но группа захвата не создается. Таким образом, двигатель продолжает работать с i
. И i
будет соответствовать i. Эта последняя попытка матча успешна. qui соответствует
Пусть применяется q(?=u)i
для выхода. Взгляд положительный, за ним следует еще один токен. Опять же, q
соответствует q и u
соответствует u. Опять же, совпадение с lookahead должно быть отброшено, поэтому двигатель отходит от i
в строке до u. Результат был успешным, поэтому двигатель продолжает работать с i
. Но i
не может совпадать с u. Таким образом, попытка совпадения не срабатывает.
Пусть применяется q(?=u)u
для выхода. Взгляд положительный, за ним следует еще один токен. Опять же, q
соответствует q и u
соответствует u. Совпадение с lookahead должно быть отброшено, поэтому двигатель отходит от u
в строке до u. Результат был успешным, поэтому двигатель продолжает u
. И u
будет соответствовать u. Таким образом, эта попытка матча успешна. qu соответствует
Пусть применяется q(?!i)u
для выхода. Даже в этом случае lookahead является положительным (потому что i
не соответствует), а за ним следует еще один токен. Опять же, q
соответствует q и i
не соответствует u. Совпадение с lookahead должно быть отброшено, поэтому двигатель отходит от u
в строке до u. Результат был успешным, поэтому двигатель продолжает u
. И u
будет соответствовать u. Таким образом, эта попытка матча успешна. qu соответствует
Итак, в заключение, реальная разница между группами просмотра и не захвата - это все, если вы хотите просто проверить существование или проверить и сохранить совпадение. Захват группы дорог, поэтому используйте ее разумно.
Ответ 4
Попробуйте сопоставить foobar
с этими:
/foo(?=b)(.*)/
/foo(?!b)(.*)/
Первое регулярное выражение будет совпадать и вернет "бар" в качестве первого подгружателя - (?=b)
соответствует "b", но не использует его, оставив его для следующих скобок.
Второе регулярное выражение НЕ будет соответствовать, потому что оно ожидает, что "foo" будет следовать чем-то отличным от "b".
(?:...)
имеет тот же эффект, что и простой (...)
, но он не возвращает эту часть в качестве подкачки.