ТОР 5 статей: Методические подходы к анализу финансового состояния предприятия Проблема периодизации русской литературы ХХ века. Краткая характеристика второй половины ХХ века Характеристика шлифовальных кругов и ее маркировка Служебные части речи. Предлог. Союз. Частицы КАТЕГОРИИ:
|
Количественные модификаторы (квантификаторы)
Обычно регулярные выражения гораздо сложнее, чем приведенные выше, и записывать их по одному символу было бы тяжеловато. Например, нужно отобрать строки, состоящие из четырех символов, каждый из которых может быть буквой от A до F или цифрой? Регулярное выражение могло бы выглядеть примерно так:
PS C:\> "af12","1FE0","1fz1","B009","C1212" -match "^[a-f\d][a-f\d][a-f\d][a-f\d]$" af12 1FE0 B009 Не слишком то лаконично, не правда ли? К счастью всю эту конструкцию можно значительно сократить. Для этого в регулярных выражениях существует специальная конструкция – " количественные модификаторы " (квантификаторы). Эти модификаторы приписываются к любой группе справа, и определяют количество вхождений этой группы. Например, количественный модификатор {4} означает 4 вхождения. Посмотрим на приведенном выше примере: PS C:\> "af12","1FE0","1fz1","B009","C1212" -match "^[a-f\d]{4}$" af12 1FE0 B009 Данное регулярное выражение полностью эквивалентно предыдущему – "4 раза по [a-f\d]". Но этот количественный модификатор не обязательно жестко оговаривает количество повторений. Например можно задать количество как "от 4 до 6". Делается это указанием внутри фигурных скобок двух чисел через запятую – минимума и максимума: PS C:\> "af12","1FE0","1fA999","B009","C1212","A00062","FF00FF9" -match "^[a-f\d]{4,6}$" af12 1FE0 1fA999 B009 C1212 A00062 Если максимальное количество вхождений безразлично, например нужно указать "3 вхождения или больше", то максимум можно просто опустить (оставив запятую на месте), например "строка состоящая из 3х или более цифр": PS C:\> "1","12","123","1234","12345" -match "^\d{3,}$" Минимальное значение опустить нельзя, но можно просто указать единицу: PS C:\> "1","12","123","1234","12345" -match "^\d{1,3}$" Как и в случае с символьными группами, для особенно популярных значений количественных модификаторов, есть короткие псевдонимы: + (плюс), эквивалентен {1,} то есть, "одно или больше вхождений" * (звездочка), то же самое что и {0,} или на русском языке – "любое количество вхождений, в том числе и 0" ? (вопросительный знак), равен {0,1} – "либо одно вхождение, либо полное отсутствие вхождений". В регулярных выражениях, количественные модификаторы сами по себе использоваться не могут. Для них обязателен символ или символьная группа, которые и будут определять их смысл. Вот несколько примеров: .+ Один или более любых символов. Аналог?* в простых подстановках (как в cmd.exe). Следующее выражение выбирает процессы, у которых имя "начинается с буквы S, затем следует 1 или более любых символов, затем снова буква S и сразу после неё конец строки". Иначе говоря "имена которые начинаются и заканчиваются на S": PS C:\> Get-Process | where {$_.name -match "^s.+s$"}
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName ------ ----- ----- ----- ------ -- ----------- 257 14 6540 5220 53 5,97 508 services 30 2 424 128 5 0,08 280 smss \S* Любое количество символов не являющихся пробелами. Подобное выражение может совпасть и с ""(с пустой строкой), ведь под любым количеством подразумевается и ноль, то есть 0 вхождений – тоже результат. PS C:\> "abc", "cab", "a c","ac","abdec" -match "a\S*c" abc ac abdec Заметьте, строка "ac" тоже совпала, хотя между буквами A и C вообще не было символов. Если заменить * на + то будет иначе: PS C:\> "abc", "cab", "a c","ac","abdec" -match "a\S+c" abc abdec
бобры? (Это не вопрос, а регулярное выражение). Последовательность "бобр", после которой может идти символ "ы", а может и отсутствовать: PS C:\> "бобр","бобры","бобрята" -match "^бобры?$" бобр бобры
1.10.5. Группы захвата и переменная $matches
Теперь, когда мы можем с помощью регулярных выражений описывать и проверять строки по достаточно сложным правилам, пора познакомится с другой не менее важной возможностью регулярных выражений – "группами захвата" (capture groups). Как следует из названия, группы можно использовать для группировки. К группам захвата, как и к символам и символьным группам, можно применять количественные модификаторы. Например, следующее выражение означает "Первая буква в строке – S, затем одна или больше групп, состоящих из “знака - (минус) и любого количества цифр за ним” до конца строки": PS C:\> "S-1-5-21-1964843605-2840444903-4043112481" -match "^S(-\d+)+$" True Или: PS C:\> "Ноут","Ноутбук","Лептоп" -match "Ноут(бук)?" Ноут Ноутбук Эти примеры показывают, как можно использовать группы захвата для группировки, но это вовсе не главное их качество. Гораздо важнее то, что часть строки, подпавшая под подвыражение, находящееся внутри такой группы, помещается в специальную переменную – $matches. $Matches - это массив, и в нем может находится содержимое нескольких групп. Причем под индексом 0 туда помещается вся совпавшая строка, начиная с единицы идет содержимое групп захвата. Рассмотрим пример: PS C:\> "At 17:04 Firewall service was stopped." -match "(\d\d:\d\d) (\S+)" True PS C:\> $matches
Name Value ---- ----- 2 Firewall 1 17:04 0 17:04 Firewall Под индексом 0 находится вся часть строки, подпавшая под регулярное выражение, под 1 находится содержимое первых скобок, и под 2 соответственно содержимое вторых скобок. К содержимому $matches можно обращаться как к элементам любого другого массива в PowerShell: PS C:\> $matches[1] 17:04 PS C:\> $matches[2] Firewall Если в строке присутствует много групп захвата, то бывает полезно дать им имена, это сильно облегчает дальнейшую работу с полученными данными: PS C:\> "At 17:04 Firewall service was stopped." -match "(?<Время>\d\d:\d\d) (?<Служба>\S+)" True
PS C:\> $matches Name Value ---- ----- Время 17:04 Служба Firewall 0 17:04 Firewall
PS C:\> $matches.Время 17:04 PS C:\> $matches["Служба"] Firewall Регулярное выражение конечно усложнилось, но зато работать с результатами гораздо приятнее. Синтаксис именования следующий: (?<Название Группы>подвыражение) Не перепутайте порядок, сначала следует знак вопроса. Количественные модификаторы, в том числе? могут применяться только после группы, и следовательно в начале подвыражения – бессмысленны. Поэтому в группах знак вопроса, следующий сразу за открывающей скобкой, означает особый тип группы, в нашем примере – именованную. Другой тип группы, который часто используется – незахватывающая группа. Она может пригодиться в тех случаях, когда не нужно захватывать содержимое группы, а надо применить её только для группировки. Например, в вышеприведённом примере с SID, такая группа была бы более уместна: PS C:\> "S-1-5-21-1964843605-2840444903-4043112481" -match "^S(?:-\d+)+$" True PS C:\> $matches
Name Value ---- ----- 0 S-1-5-21-1964843605-2840444903-4043112481 Синтаксис такой группы: (?:подвыражение). Группы можно и вкладывать одну в другую: PS C:\> "MAC address is '00-19-D2-73-77-6F'." -match "is '([a-f\d]{2}(?:-[a-f\d]{2}){5})'" True PS C:\> $matches
Name Value ---- ----- 1 00-19-D2-73-77-6F 0 is '00-19-D2-73-77-6F'
Не нашли, что искали? Воспользуйтесь поиском:
|