В чем разница между?:,?! и? = в регулярном выражении?

Я искал значение этих выражений, но не мог понять точного различия между ними. Это то, что они говорят:

  • ?: Сопоставить выражение, но не записывать его.
  • ?= Сопоставьте суффикс, но исключите его из захвата.
  • ?! Соответствует, если суффикс отсутствует.

Я попытался использовать их в простой 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".

(?:...) имеет тот же эффект, что и простой (...), но он не возвращает эту часть в качестве подкачки.