Продолжаем разговор о регулярных выражениях. В предыдущем посте я рассказал об основах, а в этом рассмотрим некоторые более “продвинутые” конструкции регулярных выражений.
Предполагается что вы уже знаете как указать регулярному выр ажению какие символы и/или их последовательности должны быть в строке для совпадения. А что если вам нужно указать не те символы которые должны присутствовать, а те которых не должно быть? То есть если вам нужно вывести лишь согласные буквы, вы можете конечно их перечислить, а можете использовать и отрицательную группу с гласными, например:
PS C:\> "a","b","c","d","e","f","g","h" -match "[^aoueyi]" b c d f g h
"Крышка" в качестве первого символа группы символов означает именно отрицание. То есть на месте группы может присутствовать любой символ кроме перечисленных в ней. Для того чтобы включить отрицание в символьных группах (\d
, \w
, \s
), не обязательно заключать их в квадратные скобки, достаточно… перевести их в верхний регистр 🙂 Например \D
будет означать "что угодно, кроме цифр", а \S
"всё кроме пробелов"
PS C:\> "a","b","1","c","45" -match "\D" a b c PS C:\> "a","-","*","c","&" -match "\W" - * &
Уже гораздо могущественнее обычных символов подстановки, не так ли? 🙂 А ведь мы только начали изучать основы! Символьные группы позволяют нам указать лишь содержимое одной позиции, один символ находящийся в неопределенном месте строки. А что если нам надо например выбрать все слова которые начинаются с буквы w
? если просто поместить эту букву в регулярное выражение, то оно совпадёт для всех строк где w
вообще встречается, и не важно — в начале, в середине или в конце строки. В таких случаях на помощь приходят "якоря". Они позволяют производить сравнение начиная с определенной позиции в строке. ^
(крышка) является якорем начала строки, а
$
(знак доллара) - обозначает конец строки. Не запутайтесь - ^
как символ отрицания используется лишь в начале группы символов, а вне группы - этот символ является уже якорем 🙂 Да, да, авторам регулярных выражений явно не хватало специальных символов, и они по возможности, использовали их более чем в одном месте (о втором значении $
поговорим позже) 🙂 Впрочем лучше посмотреть на примере:
PS C:\> Get-Process | where {$_.name -match "^w"} Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName ------- ------ ----- ----- ----- ------ -- ----------- 80 10 1460 156 47 0,11 452 wininit 114 9 2732 1428 55 0,56 3508 winlogon 162 11 3660 1652 44 0,14 3620 wisptis 225 20 5076 4308 95 31,33 3800 wisptis 469 28 9572 11904 101 3,23 1844 wlcrasvc 706 54 52452 43008 632 9,64 1072 wmdc 105 10 2308 1428 76 0,08 4056 wuauclt
Эта команда вывела процессы у которых сразу после начала имени (^
) следует символ w
. Иначе говоря имя начинается на w
. Давайте для усложнения примера, и для упрощения понимания, добавим сюда “крышку” в значении отрицательной группы:
PS C:\> Get-Process | where {$_.name -match "^w[^l-z]"} Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName ------- ------ ----- ----- ----- ------ -- ----------- 80 10 1460 156 47 0,11 452 wininit 114 9 2732 1428 55 0,56 3508 winlogon 162 11 3660 1652 44 0,14 3620 wisptis 225 20 5076 4308 95 31,50 3800 wisptis
Теперь команда вывела нам процессы у которых имя начинается с символа w
, а следующий символ является чем угодно, только не из диапазона l-z
.
Обратите внимание, примеры уже начинают походить на краказябли, а вы их уже можете понимать 🙂
Ну и для закрепления, опробуем второй якорь — конец строки:
PS C:\> "Яблоки","Груши","Дыня","Енот","Апельсины","Персик" -match "[ыи]$" Яблоки Груши Апельсины
Это выражение вывело нам все слова в которых последняя буква И
или Ы
.
Если вы можете точно описать содержимое всей строки, то вы можете использовать и оба якоря одновременно:
PS C:\> "abc","adc","aef","bca","aeb","abec","abce" -match "^a.[cb]$" abc adc aeb
Это регулярное выражение выводит все строки которые начинаются с буквы А, за которой следует один любой символ (точка), затем символ C или B и затем конец строки.
Продолжение: Квантификаторы
26.11.2009 в 18:42
Спасибо за статью.
Меня вот смущает, что набор g*45 соответствует как строке «fgd 3456» так и строке «3456 fgd». Как-то это у меня не укладывается совсем в голове.
26.11.2009 в 23:19
Более того, он будет соответствовать любой строке в которой встречается 45, независимо от других факторов и наличия буквы «g» 🙂 g* может соответствовать как «g», так «ggggg» так и нулю g, то есть «». Подробнее в следующих постах 🙂
27.11.2009 в 10:05
Век живи — век учись. Всё это время для меня * существовала сама по себе (а + и вовсе не пользовал я), без предшествующего символа. В файловых масках я имею ввиду. Больше нигде ей и не пользовался.
Вообщем жду следующую статью с нетерпением. )
26.11.2009 в 21:53
жгешь редиско
26.11.2009 в 23:20
Чойта я редиско? 😉 Я очень даже хороший человек 🙂 И очень скромный само-собой 😉
4.12.2009 в 11:26
[…] процесса на удалённом компьютере – WinRM (WS-Management)Регулярные выражения — Отрицательные группы и якоряПростенькая инвентаризация ПО на компьютерахЗапуск […]
11.12.2009 в 18:25
[…] Отрицательные группы и якоря […]
18.12.2009 в 12:51
[…] Отрицательные группы и якоря […]
24.12.2009 в 12:04
[…] Регулярные выражения – Жадность 24.12.2009 — Xaegr Просто отличное название для очередной статьи о регулярных выражениях в блоге посвященном PowerShell Но оно действительно подходит лучше всего. Сегодня мы поговорим об одной важной концепции регулярных выражений. От чего зависит сколько символов будет захвачено количественным модификатором с варьирующейся длинной? Именно от жадности Если вы наткнулись на пост случайно, то сначала лучше ознакомьтесь с предыдущими постами серии – 1,2,3,4,5. […]
28.12.2009 в 12:10
[…] разумеется Мы успели познакомится с основами, отрицательными группами и якорями, квантификаторами, группами захвата, операторами […]
28.1.2010 в 18:16
А могу ли я как-либо обозначить отрицательное слово, кроме как перечислением вида [^w][^o][^r][d^] ?
28.1.2010 в 21:07
Да, конечно. Например с помощью незахватывающей группировки:
PS D:\Temp> «word» -match «^(:?^word)$»
True
PS D:\Temp> «wort» -match «^(:?^word)$»
False
Но иногда проще использовать оператор -notmatch 🙂
24.2.2010 в 11:00
[…] на посты которые рекомендуется прочитать сначала: 1, 2, 3, 4, 5, 6, […]