Сегодня еще кое что из книги "Keith Hill, Эффективное программирование в Windows PowerShell. 2009". На сей раз еще раз про регулярные выражения.
Известно что PowerShell основан на .NET Framework. То есть, он построен с использованием .NET Framework и предоставляет возможности .NET Framework пользователю. Одна из наиболее удобных возможностей в .NET Framework - класс Regex в пространстве имён System.Text.RegularExpressions. Это очень мощный механизм регулярных выражений. PowerShell использует его в ряде сценариев с помощью:
• оператора -match
• оператора -notmatch
• параметра -Pattern командлета Select-String.
Конечно, чтобы использовать эти операторы и Select-String максимально эффективно, необходимо хорошо понимать применение регулярных выражений. Справочная система PowerShell содержит раздел с именем "about_Regular_Expression", который вы можете вызвать так:
PS> help about_reg*
Данный раздел представляет собой лишь краткое справочное руководство по различным метасимволам, с его помощью вы не научитесь создавать мощные регулярные выражения. Чтобы узнать, как получить максимальную отдачу от регулярных выражений, и, следовательно, PowerShell, я очень рекомендую прочитать книгу Jeffrey Friedl Mastering Regular Expressions (Джеффри Фридл, Регулярные выражения). В механизме поддержки регулярных выражений PowerShell существует один недостаток, который необходимо знать. Большинство других скриптовых языков поддерживают синтаксис, позволяющий обнаружить все вхождения шаблона в строке. Например, в Perl я могу сделать так:
$_ = "paul xjohny xgeorgey xringoy stu pete brian"; # PERL script
($first, $second, $third) = /x(.+?)y/g;
К сожалению, командлет Select-String не поддерживает эту возможность в версии 1.0. Тем не менее, вы можете обойти это ограничение, используя класс System.Text.RegularExpressions.Regex напрямую. Нет необходимости указывать имя класса полностью, PowerShell имеет для него псевдоним [regex].
Например:
PS> $str = "paul xjohny xgeorgey xringoy stu pete brian"
PS> $first,$second,$third = ([regex]'x(.+?)y').Matches($str) |
>>Foreach {$_.Groups[1].Value}
PS> $first
john
PS> $second
george
PS> $third
ringo
Одна из вещей, за которой необходимо тщательно следить - написание регулярного выражения для поиска во всей строке. Например, вы решили использовать Get-Content для получения содержимого файла и применения к нему регулярного выражения. В этом случае необходимо помнить, что Get-Content считывает файл частями - строка за строкой. Для применения регулярного выражения ко всему содержимому файла, необходимо будет преобразовать это содержимое в одну строку. Я могу сделать это в PowerShell 1.0, например, так:
PS> $regex = [regex]'(?<CMultilineComment>/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)'
PS> Get-Content foo.c | Join-String -Newline | Foreach {$regex.Matches($_)} |
>> Foreach {$_.Groups["CMultilineComment"].Value}
>>
Здесь я использовал командлет Join-String, разработанный PowerShell Community Extensions, который принимает отдельные строки, выводимые Get-Content, и создаёт из них одну строку. Также в примере использован именованный захват CMultilineComment. Этот пример демонстрирует, что при отсутствии возможностей в самом PowerShell, использование среды .NET может стать замечательным "запасным выходом".
Начиная с версии PowerShell 2.0 появились новые возможности, помогающие выполнять поиск в вышеописанном случае. Во-первых, добавлен оператор объединения, с помощью которого можно соединять многострочный текст в одну строку. Во-вторых, в Select-String появились новые параметры, такие как -Context, -NotMatch и -AllMatches. Параметр AllMatches как раз подходит для решения предыдущей задачи. Вот как можно теперь выполнить поиск комментариев:
$pattern = '(?<CMultilineComment>/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)'
PS> (get-content .\foo.c) -join "`n" | Select-String $pattern -all |
>>Foreach {$_.Matches} | Foreach {$_.Value}
Использование регулярных выражений - очень мощный инструмент PowerShell. Научитесь его использовать, и он откроет вам много возможностей поиска и обработки текстовых данных.
No comments:
Post a Comment
А что вы думаете по этому поводу?