PowerShell: регулярные выражения

Мне достаточно часто задают вопросы связанные не столько с самим PowerShell, сколько с применением в нем регулярных выражений. Это и понятно — регулярные выражения (или если сокращенно “регэкспы” (regexp, regular expressions)) обладают огромной мощью, и способны сильно упростить жизнь системного администратора или программиста. Однако в мире системного администрирования Windows они мало известны и непопулярны — в cmd.exe практически единственная возможность их применения это утилита findstr.exe, которая обладает очень маленьким функционалом и использует жутко урезанный диалект регулярных выражений.

В VBScript функционал регулярных выражений тоже хорошо запрятан, и практически не используется. А вот в PowerShell, авторы языка позаботились о том чтобы регулярные выражения были легко доступны, удобны в использовании и максимально функциональны. Тем более что с последним пунктом всё оказалось достаточно просто — PowerShell использует реализацию регулярных выражений .NET, а она является одной из самых функциональных и производительных, и даже способна потягаться даже с признанным лидером в этой области — perl’ом

Итак, перейдем к делу. Что же такое регулярные выражения? Я не помню правильных и сухих определений из умных книжек, да и незачем, кому интересно — прочитает их сам Регулярные выражения это специальный мини-язык служащий для разбора (parsing) текстовых данных. С его помощью можно разделять строки на компоненты, выбирать нужные части строк для дальнейшей обработки, производить замены, и всё это с огромной гибкостью и точностью.

Впрочем… знакомство с регулярными выражениями лучше начать не с них, а с более простой технологии которая служит подобным целям, с которой знакомы все Windows администраторы – с подстановочных символов. Наверняка вы не раз выполняли команду dir, и указывали ей в качестве аргумента маску файла, например *.exe. В данном случае звёздочка означает “любое количество любых символов”. Аналогично можно использовать и знак вопроса, он будет означать “один любой символ”, то есть dir ??.exe выведет все файлы с расширением .exe и именем из двух символов. В PowerShell’овской реализации подстановочных символов можно применять и еще одну конструкцию — группы символов. Так например [a-f] будет означать “один любой символ от a до f (a,b,c,d,e,f) ”, а [smw] любую из трех букв (s, m или w). Таким образом команда get-childitem [smw]??.exe выведет файлы с расширением .exe, у которых имя состоит из трех букв, и первая буква либо s, либо m, либо w. Неплохо, неправда ли? Так вот, по сравнению с возможностями регулярных выражения — это ерунда Но начнём с малого

Для начала изучения мы будем использовать оператор PowerShell -match, который позволяет сравнивать текст слева от него, с регулярным выражением справа. В случае если текст подпадает под регулярное выражение, оператор выдаёт True, иначе — False.

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

Еще одна тонкость: оператор -match по умолчанию не чувствителен к регистру символов (как и другие текстовые операторы в PowerShell), если же вам нужна чувствительность к регистру, используйте -cmatch:

В регулярных выражениях можно использовать и группы символов:

И диапазоны в этих группах:

Кстати тут я в левой части оператора -match поместил массив строк, и он соответственно вывел лишь те строки, которые подошли под регулярное выражение.

Разумеется перечисления символов можно комбинировать, например группа [агдэ-я] будет означать “А или Г или Д или любой символ от Э до Я включительно”. Но гораздо интереснее использовать диапазоны для определения целых классов символов. Например [а-я] будет означать любую букву русского алфавита, а [a-z] английского. Аналогично можно поступать с цифрами — следующая команда выведет все процессы в именах которых встречаются цифры:

Так как эта группа используется достаточно часто, для неё была выделена специальная последовательность — \d (от слова digit). По смыслу она полностью идентична [0-9], но гораздо короче

Так же последовательность была выделена для группы “любые буквы любого алфавита, любые цифры, или символ подчеркивания” эта группа обозначается как \w (от word) она примерно эквивалентна конструкции [a-zа-я_0-9]\w еще входят символы других алфавитов которые используются для написания слов).

Еще вам наверняка встретится другая популярная группа: \s — “пробел, или другой пробельный символ” (например символ табуляции). Сокращение от слова space. В большинстве случаев вы можете обозначать пробел просто как пробел но эта конструкция добавляет читабельности регулярному выражению.

Не менее популярной группой можно назвать символ . (точка). Точка в регулярных выражениях аналогична по смыслу знаку вопроса в подстановочных символах, то есть обозначает один любой символ.

Все вышеперечисленные конструкции можно использовать как отдельно, так и в составе групп, например [\s\d] будет соответствовать любой цифре или пробелу. Если вы хотите указать внутри группы символ - (тире/минус) то надо либо экранировать его символом \ (обратный слеш), либо поставить его в начале группы, чтобы он не был случайно истолкован как диапазон:

Отрицательные группы и якоря

Вы уже знаете как указать регулярному выражению какие символы и/или их последовательности должны быть в строке для совпадения. А что если вам нужно указать не те символы которые должны присутствовать, а те которых, наоборот, не должно быть? То есть если вам нужно вывести лишь согласные буквы, вы можете конечно их перечислить их все, а можете использовать и отрицательную группу с гласными, например:

«Крышка» в качестве первого символа группы символов означает именно отрицание. То есть на месте группы может присутствовать любой символ кроме перечисленных в ней. Для того чтобы включить отрицание в символьных группах (\d, \w, \s), не обязательно заключать их в квадратные скобки, достаточно… перевести их в верхний регистр Например \D будет означать «что угодно, кроме цифр», а \S «всё кроме пробелов»

Уже гораздо могущественнее обычных символов подстановки, не так ли? А ведь мы только начали изучать основы! Символьные группы позволяют нам указать лишь содержимое одной позиции, один символ находящийся в неопределенном месте строки. А что если нам надо например выбрать все слова которые начинаются с буквы w? если просто поместить эту букву в регулярное выражение, то оно совпадёт для всех строк где w вообще встречается, и не важно — в начале, в середине или в конце строки. В таких случаях на помощь приходят «якоря». Они позволяют производить сравнение начиная с определенной позиции в строке. ^<code> (крышка) является якорем начала строки, а <code>$ (знак доллара) — обозначает конец строки. Не запутайтесь — ^ как символ отрицания используется лишь в начале группы символов, а вне группы — этот символ является уже якорем Да, да, авторам регулярных выражений явно не хватало специальных символов, и они по возможности, использовали их более чем в одном месте (о втором значении $ поговорим позже) Впрочем лучше посмотреть на примере:

Эта команда вывела процессы у которых сразу после начала имени (^) следует символ w. Иначе говоря имя начинается на w<code>. Давайте для усложнения примера, и для упрощения понимания, добавим сюда "крышку" в значении отрицательной группы:

Теперь команда вывела нам процессы у которых имя начинается с символа w, а следующий символ является чем угодно, только не из диапазона l-z.

Обратите внимание, примеры уже начинают походить на модзибакэ, а вы их уже можете понимать

Ну и для закрепления, опробуем второй якорь — конец строки:

Это выражение вывело нам все слова в которых последняя буква И или Ы.

Если вы можете точно описать содержимое всей строки, то вы можете использовать и оба якоря одновременно:

Это регулярное выражение выводит все строки которые начинаются с буквы А, за которой следует один любой символ (точка), затем символ C или B и затем конец строки.

Квантификаторы

Что ж, мы уже немало узнали о символьных группах и якорях. Это неплохое начало, но обычно регулярные выражения гораздо сложнее, и записывать их по одному символу было бы тяжеловато. Что если вам нужно отобрать строки состоящие из четырех символов, каждый из которых может быть буквой от A до F или цифрой? Регулярное выражение могло бы выглядеть примерно так:

Не слишком то лаконично, не правда ли? К счастью всю эту конструкцию можно значительно сократить. Для этого в регулярных выражениях существует специальная концепция — «количественные модификаторы» (квантификаторы). Эти модификаторы приписываются к любой группе справа, и оговаривают количество вхождений этой группы. Например количественный модификатор {4} означает 4 вхождения. Посмотрим на нашем примере:

Данное регулярное выражение полностью эквивалентно предыдущему — “4 раза по [a-f\d]”. Но этот количественный модификатор не обязательно жестко оговаривает количество повторений. Можно например задать количество как «от 4 до 6». Делается это указанием внутри фигурных скобок двух чисел через запятую — минимума и максимума:

Если вам безразлично максимальное количество вхождений, например вы хотите указать «3 вхождения или больше», то максимум можно просто опустить (оставив запятую на месте), например «строка состоящая из 3х или более цифр»:

Минимальное значение опустить не получится, впрочем можно просто указать единицу:

Как и в случае с символьными группами, для особенно популярных значений количественных модификаторов, есть короткие псевдонимы:

+ (плюс), эквивалентен {1,} то есть, «одно или больше вхождений»

* (звездочка), то же самое что и {0,} или если на русском языке — «любое количество вхождений, в том числе и 0»

? (вопросительный знак), равен {0,1} — «либо одно вхождение, либо полное отсутствие вхождений».

Помните, в регулярных выражениях, количественные модификаторы сами по себе использоваться не могут. Для них обязателен символ или символьная группа, которые и будут определять их смысл. Вот несколько примеров:

.+ Один или более любых символов. Аналог ?* в простых подстановках (как в cmd.exe). Следующее выражение выбирает процессы у которых имя «начинается с буквы S, затем следует 1 или более любых символов, затем снова буква S и сразу после неё конец строки». Иначе говоря «имена которые начинаются и заканчиваются на S»:

\S* Любое количество символов не являющихся пробелами. Помните, подобное выражение может совпасть и с “”(с пустой строкой), ведь под любым количеством подразумевается и ноль, то есть 0 вхождений — тоже результат.

Заметьте, строка «ac» тоже совпала, хотя между буквами A и C вообще не было символов. Если заменить * на + то будет иначе:

бобры? (Это был не вопрос, а регулярное выражение ) Последовательность «бобр», после которой может идти символ «ы», а может и отсутствовать:

Группы захвата

Теперь, когда мы можем с помощью регулярных выражений описывать и проверять строки по достаточно сложным правилам, пора познакомится с другой не менее важной концепцией регулярных выражений — «группами захвата» (capture groups). Как следует из названия, группы можно использовать для … сюрприз … группировки К группам захвата, как и к символам и символьным группам можно применять количественные модификаторы. Например следующее выражение означает «Первая буква в строке — S, затем одна или больше групп состоящих из “знака - (минус) и любого количества цифр за ним” до конца строки»:

Эти примеры показывают как можно использовать группы захвата для группировки, но это вовсе не главное их качество Гораздо важнее то, что часть строки подпавшая под подвыражение находящееся внутри такой группы, помещается в специальную переменную — $matches. $Matches это массив, и в нем может находится содержимое нескольких групп. Причем под индексом 0 туда помещается вся совпавшая строка, а лишь начиная с единицы идет содержимое групп захвата. Опять же, лучше посмотреть на примере:

Под индексом 0 находится вся часть строки подпавшая под регулярное выражение, под 1 находится содержимое первых скобок, и под 2 соответственно содержимое вторых скобок. К содержимому $matches можно обращаться как к элементам любого другого массива в PowerShell:

Если в строке присутствует много групп захвата, то бывает полезно дать им имена, это сильно облегчает дальнейшую работу с полученными данными:

Регулярное выражение конечно усложнилось, но зато работать с результатами гораздо приятнее. Синтаксис именования следующий:

(?<Название Группы>подвыражение)

Не перепутайте порядок, сначала следует знак вопроса. Как вы помните, количественные модификаторы, в том числе ? могут применяться только после группы, и следовательно в начале подвыражения — бессмысленны. Поэтому в группах, знак вопроса следующий сразу за открывающей скобкой, означает особый тип группы, в нашем примере — именованную.

Другой тип группы который часто используется – незахватывающая группа. Она может пригодиться в тех случаях когда вам не нужно захватывать содержимое группы, а надо применить её только для группировки. Например в вышеприведённом примере с SID, такая группа была бы более уместна:

Как вы могли заметить, синтаксис такой группы: (?:подвыражение). Группы можно и вкладывать одну в другую:

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

Операторы -replace и -split

Мы уже научились не просто проверять строки на соответствие правилам, но и извлекать из них самое интересное содержимое. Но регулярные выражения позволяют не только анализировать строки, но и изменять их. Так что пора познакомиться с еще одним оператором PowerShell, который использует в своей работе регулярные выражения — -replace. Слева от этого оператора указывается обрабатываемая строка, а справа массив состоящий из двух элементов: первый — регулярное выражение определяющее что заменяем, и второй элемент — строка на которую заменяем.

Давайте посмотрим пример:

Так как мы уже знаем некоторые возможности регулярных выражений, мы можем использовать оператор более интересным способом:

Оператор -replace замещает всю совпавшую часть выражения, то есть то что в $matches находилось бы под индексом 0. Впрочем в -replace можно использовать и группы захвата. Вместо помещения в $matches, захваченные данные подставляются во второй элемент массива (то на что заменяем) с помощью символа доллара, и индекса группы, например $0 — всё совпавшее выражение, $1 — содержимое первой группы, $2 — второй, и так далее. Обратите внимание, не только в регулярных выражениях символ $ имеет дополнительные значения (якорь конца строки), но и в самом PowerShell. Так что если просто вставить $1 в строку окруженную двойными кавычками, то PowerShell попытается подставить туда значение переменной $1, а так как такой скорее всего не существует, то он просто заменит эту последовательность на пустоту. Чтобы этого не произошло, а $1 был бы обработан оператором -replace, следует использовать одинарные кавычки (внутри которых PowerShell не раскрывает переменные):

У оператора -replace, как и у других операторов PowerShell для работы со строками, есть и версия отличающая верхний и нижний регистр символов:

Не все об этом знают, но второй элемент массива справа от -replace необязательный. Если его опустить, то команда будет выполнять замену на "" (пустоту). Именно поэтому и нет оператора -remove Например уберём из текста всё кроме цифр:

Ну и раз уж взялись за номера телефонов, отформатируем эту последовательность в нужном нам формате

Другой оператор, похожий на -replace, это -split. Он появился только во второй версии PowerShell. В отличии от -replace, он разделяет строку на части и возвращает массив строк. Справа от него указывается регулярное выражение по которому он будет делить строку. В следующем примере это пробел или знак минуса:

Еще ему можно указать максимальное количество частей в результате:

То есть, после достижения указанного количества результатов, дальнейшее деление не происходит.

Жадность

По умолчанию, все количественные модификаторы в регулярных выражениях — жадные. То есть они пытаются захватить как можно больше символов (разумеется пока это позволяют условия). Взять к примеру .+ Это выражение означает 1 или более вхождений, но разве оно остановится на одном вхождении? Нет! Оно будет жрать захватывать символы пока у него будет эта возможность, то есть до ограничителя если он есть, а если его нет — то до конца (или начала) строки. Например:

Заметьте, захавал всё, и даже точкой не подавился А что если мы допускаем любое количество повторений группы, но хотим ограничиться минимумом? Тогда нам поможет «нежадная» версия этого количественного модификатора:

Да, просто добавив после этого количественного модификатора вопросительный знак, мы сразу заставили его ограничится минимумом — одним символом. Нежадные версии других количественных модификаторов получаются таким же образом: *? ?? {1,5}?

Разумеется нежадный модификатор может захватить и больше, но только если у него не останется другого выбора:

В этом выражении оговаривается что \S+? должен захватить минимум, но до следующей точки.

Маскировка служебных символов в регулярных выражениях, в отличии от других строк PowerShell, делается с помощью символа \ Например

\. Точка
\( Открывающая скобка
\\ Обратный слеш

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

И еще один пример полезности нежадных квантификаторов:

Впрочем… конкретно в этой ситуации можно поступить и иначе:

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

Разумеется подобные «нежадные» модификаторы можно использовать не только в -replace:

В случае если в выражении присутствует несколько количественных модификаторов, которые могут захватить одну и ту же часть строки, то приоритет будет у первого. Но первый всегда уступит следующему, если это необходимо для совпадения выражения:

Тут первый \d+ захватил максимум цифр, оставив второму лишь минимально необходимое для него – одну. Если же использовать нежадные версии, то первый квантификатор постарается захватить минимум, а уж всё остальное придётся захватывать второму:

Select-String

Пришло время познакомится с целым командлетом PowerShell, который использует регулярные выражения. Таким командлетом является Select-String. Он используется для поиска строк совпадающих с регулярным выражением. Строки для отбора можно передать из массива строк, например:

Еще можно указывать файлы для проверки содержащихся в них строк, просто указав их путь, или маску (с помощью обычных подстановочных знаков). Так в следующем примере я делаю поиск строки error:<code> во всех файлах <code>*.log в папке c:\Windows:

Select-String отличается от конструкции where {$_ -match "error:"} тем что выводит не просто совпадения строк, а полноценные объекты содержащие дополнительную информацию. В данном случае были выведены не только совпавшие строки, но и файлы в которых они были найдены (TSSysprep.log и WindowsUpdate.log), и номера строк. Полный список доступных свойств можно посмотреть следующей командой:

Давайте например выведем только имена файлов и номера совпавших строк:

Если весь этот «объектный мусор» вам не нужен, вы можете получить только строки, следующей командой:

У Select-String есть и несколько дополнительных возможностей. Так если вам не интересно знать какие строки совпали, а лишь необходимо выяснить были ли совпадения вообще, воспользуйтесь ключом -Quiet:

Эта команда проверяет, содержится ли в выводе netsh строка совпадающая с Enabled:\s+Yes и если содержится, то выводит значение $True. Разумеется тут тоже можно указывать напрямую имя файла или несколько с помощью подстановочных символов, тогда True будет выдано в случае если хотя бы один из файлов содержит указанную строку.

Параметр -List говорит Select-String что нужно найти лишь по одному совпадению на каждый файл. Это может быть полезно если вам надо найти все файлы содержащие определенную строку:

В PowerShell 2.0 у Select-String появился еще один очень полезный ключ — -Context. Он позволяет вывести не только совпавшую строку, но еще и указанное количество строк до неё и после неё. В следующем примере выводится 3 строки предшествующих совпадению и одна после него:

Непосредственно совпавшая строка помечается с помощью символа > в начале строки. Если указать в качестве аргумента не массив из двух элементов, а просто число, то будет выведено указанное количество строк с обоих сторон от совпадения:

В Select-String тоже можно использовать группы захвата, хотя получить их содержимое несколько сложнее. Дело в том что тут не используется специальная переменная $Matches, а вместо неё результаты совпадения, в виде объекта System.Text.RegularExpressions.Match помещаются в свойство Matches результирующего объекта. Подробнее устройство этого объекта мы рассмотрим позднее, когда будем изучать класс [Regex], а пока я просто покажу как же можно получить например значение первой группы захвата:

Другие полезные параметры командлета на которые стоит обратить внимание, это -CaseSensetive, -Encoding и -NotMatch. Их названия говорят сами за себя, поэтому не буду показывать примеры для каждого.

Switch

Давайте теперь рассмотрим конструкцию Switch, которая тоже может задействовать регекспы, и в результате становится вдвое полезнее

Сначала хорошо бы вспомнить что такое вообще switch Наверняка вы уже знакомы, но всё же… В switch вы указываете некоторую переменную, и несколько блоков кода с вариантами действий, в зависимости от значения этой переменной. Например:

Разумеется на самом деле возможности несколько богаче. К примеру вместо переменной можно указать подвыражение PowerShell, а вместо конкретных вариантов чисел, задать другие скриптблоки:

Но и этого команде PowerShell показалось мало, и они добавили несколько дополнительных возможностей. Нас впрочем интересует лишь одна из них, ключ -regex. Вообще ничего сложного в нём нет — он добавляется после ключевого слова switch, и перед выражением с данными, и заставляет switch интерпретировать варианты значений как регулярные выражения:

В вышеприведенном примере я указал в качестве источника значений содержимое файла win.ini, а в качестве вариантов — два регулярных выражения. При работе такой конструкции, каждая строчка проверяется на совпадения с каждым регулярным выражением, и в случае совпадения выполняется соответствующий блок кода.

Вот еще один пример, в нём я использую командлет foreach-object для того чтобы передавать в switch элементы для обработки по очереди. Это позволяет начать получать результаты не дожидаясь окончания выполнения команды.

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

Дело в том что даже если строчка уже совпала с первым выражением и код выполнился, после этого она будет сравниваться со следующим, и так далее. Чтобы этого не происходило, можно добавить в конце кода ключевое слово break, тогда после выполнения этого блока кода, будет осуществлен выход из switch:

Как вы могли убедится, switch очень хорошо подходит для разбора вывода консольных команд и преобразования их в объекты, а так же для разбора конфигурационных файлов. Аналогично его можно использовать и для работы с файлами текстовых логов, особенно в тех случаях когда записи не следуют единому правилу.

Regex

Ну и напоследок выглянем за пределы стандартных командлетов и операторов, и воспользуемся для работы с регулярными выражениями, так называемым, «сырым» .NET Это не так страшно как может показаться, зато очень полезно, и зачастую просто необходимо.

Работать мы будем с классом .NET, полное имя которого звучит как System.Text.RegularExpressions.Regex, но к счастью в PowerShell для него есть адаптер-ярлык, позволяющий называть его просто [Regex]. Давайте рассмотрим этот класс поближе. У него есть несколько интересных нам статических методов. Статические — значит для их вызова не требуется создавать объект класса, а можно вызывать напрямую. Посмотреть список таких методов можно командлетом Get-Member с ключом -Static:

На всякий случай, напомню основные особенности синтаксиса статических методов .NET:

  • Во-первых, для вызова статического метода класса используется конструкция [класс]::метод()
  • Во-вторых, в отличии от параметров командлетов и функций, для передачи параметров методам .NET они помещаются в скобки сразу за именем метода, и разделяются запятой, например: [класс]::метод(параметр1,параметр2)
  • В отличии от «родных» конструкций PowerShell, все .NET сравнения по умолчанию чувствительны к регистру символов.

Теперь можно приступать Сначала рассмотрим метод IsMatch. Он принимает два параметра: строку текста и регулярное выражение с которым сравнивается эта строка. В качестве результата он возвращает либо True либо False:

Всё очень просто, даже проще -match

Далее возьмем Replace, у него уже 3 параметра: строка, регулярное выражение, и текст для замены. Ну и возвращает он, как можно догадаться уже измененный текст.

В этом методе уже можно использовать группы захвата, и вставлять их значения в текст для замены используя переменные $1 $2 и т.д.

Ну и последний из простых методов, это Split, он, как нетрудно догадаться принимает в качестве первого параметра текст, а в качестве второго регулярное выражение по которому он будет резать текст на части. Результат соответственно — массив строк:

Теперь перейдем к самому интересному — это метод Match. Как и метод IsMatch он принимает как параметры текст, и регулярное выражение. Но вот его результат — сильно отличается. Он возвращает не простой ответ True/False, а целый объект класса System.Text.RegularExpressions.Match, содержащий результаты сравнения.

Разберём его возможности.

В свойстве Success содержится булево значение, показывающее было ли сравнение успешным. Index — показывает номер символа в тексте начиная с которого выражение совпало. Length — длинна совпавшего текста. Value – сам совпавший текст (если бы использовался -match, то это значение было бы в $matches[0]).

В свойстве Groups содержится коллекция объектов такого же класса Match, но для каждой группы захвата (включая нулевую):

Таким образом чтобы собрать вручную аналог переменной $matches, нужно собрать все значения свойства value у объектов содержащихся в Groups, например так:

Еще у объекта Match, есть метод NextMatch, который не требует аргументов, и возвращает следующий объект Match в данной строке, если такой есть. С его помощью можно реализовать пошаговый перебор всех совпадений, например:

Впрочем обычно такую задачу можно решить еще проще, с помощью метода [Regex]::Matches<code>. Он сразу возвращает коллекцию объектов <code>Match для всех совпадений в строке. Например получим все ссылки со страницы http://ya.ru:

Вот так вот просто

Все методы которые я перечислил выше, позволяют указывать еще дополнительный параметр — RegexOptions. В нём можно задавать всевозможные опции для выполнения сравнения, такие как IgnoreCase (игнорирование регистра символов) или Compiled (выражение компилируется при первом сравнении, и последующие выполняются быстрее). Список опций можно посмотреть тут.

Еще маленькая тонкость, не обязательно использовать статические методы и постоянно указывать опции и регулярное выражение. Можно создать экземпляр класса Regex, задать опции в нём, и использовать уже обычные, не статические методы:

или так:

Как можно видеть, здесь указывается уже меньше параметров, так как регулярное выражение уже задано в объекте метод которого мы вызываем.

Ну и в качестве бонуса, еще два метода класса [Regex]Escape и Unescape. Как несложно догадаться они служат для маскировки текстовых строк для их безопасного использования в регулярных выражениях, и обратного преобразования.

После такого преобразования текст можно спокойно использовать как компонент в регулярных выражениях, не опасаясь что какие то знаки из него будут интерпретированы как спецсимволы. Ну и Unescape преобразовывает текст обратно:

На этом пока всё

источник