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

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

В моем домашнем каталоге у меня есть папка 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/ кроме сайтов /all и sites/default, которые она включает.

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

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

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

Это обычная задача, использующая регулярные выражения для

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

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

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

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

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

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

i.e:

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

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

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

???

- Обновить два:

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

4b9b3361

Ответ 1

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

Возьмем упрощенный пример:

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. Вложенный негативный lookahead становится положительным: c должен присутствовать.

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

Ответ 2

Взгляды могут быть вложенными.

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

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

Ответ 3

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

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.