Регулярное выражение отрицательный взгляд

В моем домашнем каталоге у меня есть папка drupal-6.14, которая содержит платформу Drupal.

Из этого каталога я использую следующую команду:

find drupal-6.14 -type f -iname '*' | grep -P 'drupal-6.14/(?!sites(?!/all|/default)).*' | xargs tar -czf drupal-6.14.tar.gz

Эта команда делает gzips папку drupal-6.14, исключая все подпапки drupal-6.14/sites/ кроме sites/all и sites / default, которые она включает.

Мой вопрос по регулярному выражению:

grep -P 'drupal-6.14/(?!sites(?!/all|/default)).*'

Выражение работает для исключения всех папок, которые я хочу исключить, но я не совсем понимаю, почему.

Это обычная задача с использованием регулярных выражений для

Соответствует всем строкам, кроме тех, которые не содержат подшаблон x. Или, другими словами, отрицание подшаблона.

Я (думаю) понимаю, что общей стратегией для решения этих проблем является использование негативных взглядов, но я никогда не понимал до удовлетворительного уровня, как работают позитивные и негативные взгляды (впереди / позади).

За эти годы я прочитал много сайтов на них. Руководства по регулярным выражениям PHP и Python, другие страницы, такие как http://www.regular-expressions.info/lookaround.html и т. Д., Но у меня никогда не было четкого понимания их.

Может ли кто-нибудь объяснить, как это работает, и, возможно, привести несколько похожих примеров, которые бы делали подобные вещи?

- Обновите один:

Относительно ответа Andomar: может ли двойной отрицательный прогноз быть более кратко выражен в виде одного положительного прогнозного заявления:

то есть

'drupal-6.14/(?!sites(?!/all|/default)).*'

эквивалентно:

'drupal-6.14/(?=sites(?:/all|/default)).*'

???

- Обновление два:

Что касается @andomar и @alan moore - вы не можете поменять местами двойной отрицательный взгляд на положительный взгляд.

3 ответа

Решение

Отрицательный взгляд говорит, что в этой позиции следующее регулярное выражение может не совпадать.

Давайте возьмем упрощенный пример:

a(?!b(?!c))

a      Match: (?!b) succeeds
ac     Match: (?!b) succeeds
ab     No match: (?!b(?!c)) fails
abe    No match: (?!b(?!c)) fails
abc    Match: (?!b(?!c)) succeeds

Последний пример - двойное отрицание: он позволяет b с последующим c, Вложенный отрицательный взгляд становится положительным взглядом: c должен присутствовать.

В каждом примере только a совпадает. Предварительный просмотр является только условием и не добавляет к сопоставленному тексту.

Lookarounds могут быть вложенными.

Таким образом, это регулярное выражение соответствует "drupal-6.14/", за которым не следует "sites", за которым не следует "/ all" или "/ default".

Смешение? Используя разные слова, мы можем сказать, что он соответствует "drupal-6.14/", за которым не следует "sites", если за ним не следует "/ all" или "/ default"

Если вы измените свое регулярное выражение следующим образом:

drupal-6.14/(?=sites(?!/all|/default)).*
             ^^

... тогда он будет соответствовать всем входам, которые содержат drupal-6.14/ с последующим sites сопровождаемый чем-либо кроме /all или же /default, Например:

drupal-6.14/sites/foo
drupal-6.14/sites/bar
drupal-6.14/sitesfoo42
drupal-6.14/sitesall

изменения ?= в ?! чтобы соответствовать вашему исходному регулярному выражению, просто отменяет эти соответствия:

drupal-6.14/(?!sites(?!/all|/default)).*
             ^^

Итак, это просто означает, что drupal-6.14/ теперь не может сопровождаться sites сопровождаемый чем-либо кроме /all или же /default, Итак, теперь эти входные данные будут удовлетворять регулярному выражению:

drupal-6.14/sites/all
drupal-6.14/sites/default
drupal-6.14/sites/all42

Но что может быть неочевидно из некоторых других ответов (и, возможно, вашего вопроса), так это то, что ваше регулярное выражение также разрешит другие входные данные, где drupal-6.14/ сопровождается чем-либо кроме sites также. Например:

drupal-6.14/foo
drupal-6.14/xsites

Вывод: Итак, ваше регулярное выражение в основном говорит, чтобы включить все подкаталоги drupal-6.14 кроме тех подкаталогов sites чье имя начинается с чего-либо, кроме all или же default,

Другие вопросы по тегам