Просто отличное название для очередной статьи о регулярных выражениях в блоге посвященном PowerShell 🙂 Но оно действительно подходит лучше всего. Сегодня мы поговорим об одной важной концепции регулярных выражений. От чего зависит сколько символов будет захвачено количественным модификатором с варьирующейся длинной? Именно от жадности 🙂 Если вы наткнулись на пост случайно, то сначала лучше ознакомьтесь с предыдущими постами серии — 1,2,3,4,5.
По умолчанию, все количественные модификаторы в регулярных выражениях — жадные. То есть они пытаются захватить как можно больше символов (разумеется пока это позволяют условия). Взять к примеру .+
Это выражение означает 1 или более вхождений, но разве оно остановится на одном вхождении? Нет! Оно будет жрать захватывать символы пока у него будет эта возможность, то есть до ограничителя если он есть, а если его нет — то до конца (или начала) строки. Например:
PS C:\> "Очень вкусная булка." -replace "б\S+" Очень вкусная
Заметьте, захавал всё, и даже точкой не подавился 🙂 А что если мы допускаем любое количество повторений группы, но хотим ограничиться минимумом? Тогда нам поможет "нежадная" версия этого количественного модификатора:
PS C:\> "Очень вкусная булка." -replace "б\S+?" Очень вкусная лка.
Да, просто добавив после этого количественного модификатора вопросительный знак, мы сразу заставили его ограничится минимумом — одним символом. Нежадные версии других количественных модификаторов получаются таким же образом: *? ?? {1,5}?
Разумеется нежадный модификатор может захватить и больше, но только если у него не останется другого выбора:
PS C:\> "Очень вкусная булка." -replace "б\S+?\." Очень вкусная
В этом выражении оговаривается что \S+? должен захватить минимум, но до следующей точки.
Маскировка служебных символов в регулярных выражениях, в отличии от других строк PowerShell, делается с помощью символа
\
Например
\.
Точка \(
Открывающая скобка \\
Обратный слеш Это традиционно для регулярных выражений, и обеспечивает возможность использовать в PowerShell без изменения выражения из других источников, и наоборот.
И еще один пример полезности нежадных квантификаторов:
PS C:\> "Теги <123> надо удалить <456>." -replace '<.+>' Теги . PS C:\> "Теги <123> надо удалить <456>." -replace '<.+?>' Теги надо удалить .
Впрочем… конкретно в этой ситуации можно поступить и иначе:
PS C:\> "Теги <123> надо удалить <456>." -replace '<[^>]+>' Теги надо удалить .
В тех случаях где это возможно, лучше выбирать второй вариант, он несколько производительнее.
Разумеется подобные "нежадные" модификаторы можно использовать не только в -replace
:
PS C:\> "Число 123." -match '\d+' True PS C:\> $matches Name Value ---- ----- 0 123 PS C:\> "Число 123." -match '\d+?' True PS C:\> $matches Name Value ---- ----- 0 1
В случае если в выражении присутствует несколько количественных модификаторов, которые могут захватить одну и ту же часть строки, то приоритет будет у первого. Но первый всегда уступит следующему, если это необходимо для совпадения выражения:
PS C:\Windows\system32> if ('123456' -match '^(\d+)(\d+)$') {$matches} Name Value ---- ----- 2 6 1 12345 0 123456
Тут первый \d+
захватил максимум цифр, оставив второму лишь минимально необходимое для него – одну. Если же использовать нежадные версии, то первый квантификатор постарается захватить минимум, а уж всё остальное придётся захватывать второму:
PS C:\Windows\system32> if ('123456' -match '^(\d+?)(\d+?)$') {$matches} Name Value ---- ----- 2 23456 1 1 0 123456
Продолжение: Select-String
28.12.2009 в 12:10
[…] операторами –replace и –split, а так же с концепцией “жадности”. Пришло время познакомится с целым командлетом […]
24.2.2010 в 11:01
[…] которые рекомендуется прочитать сначала: 1, 2, 3, 4, 5, 6, […]
6.4.2010 в 10:23
[…] – нежадная группа захвата, которая захватит и сохранит для нас […]