Регулярные выражения – Switch

regexp-8 Ну чтож, пора новогодних каникул давно закончилась, и мне стало уже тяжело находить отмазки на вопросы о продолжении серии🙂 Так как времени с момента предыдущего поста прошло уже немало времени, да и для тех кто натолкнулся на этот пост случайно – вот ссылки на посты которые рекомендуется прочитать сначала: 1, 2, 3, 4, 5, 6, 7.

В последнем выпуске мы познакомились с Select-String, командлетом PowerShell который использует в своей работе регулярные выражения. Сегодня же мы рассмотрим конструкцию Switch, которая тоже может задействовать регекспы, и в результате становится вдвое полезнее🙂

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

switch ($n)            
{            
    1 {Write-Host "Единица"}            
    2 {Write-Host "Двойка"}            
    3 {Write-Host "Тройка"}            
    default {Write-Host "Другое число"}            
}

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

switch (get-process | where {$_.path -like "c:\windows\*"})            
{            
    {$_.Handles -gt 300} {"у $($_.Name) слишком много handle'ов"}            
    {$_.Handles -le 100} {"у $($_.Name) очень мало handle'ов"}            
}

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

switch -regex (Get-Content C:\Windows\win.ini)            
{            
    "^\[(.+)\]$" {"Секция '" + $matches[1] + "'"}            
    "^([^=]+)=(.*)$" {"Ключ '" + $matches[1] + "' со значением '" + $matches[2] + "'"}            
}            

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

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

C:\SysInternals\tcpvcon.exe -n | foreach {switch -regex ($_)            
    {            
        "\[(.+)\] (.+)" {            
            if ($Obj) {$Obj}            
            $Obj = New-Object PSObject -Property @{Protocol=$Matches[1]; Executable=$Matches[2]}            
        }            
        "(\S+):\s+(\S.*)$" {            
            $Obj | Add-Member noteproperty -Name $Matches[1] -Value $Matches[2]            
        }            
    }            
}            

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

PS C:\> switch -regex ("word") {
>> "^w" {"$_ starts with letter 'w'"}
>> "^\w+$" {"$_ is word"}
>> }
>>
word starts with letter 'w'
word is word

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

PS C:\> switch -regex ("word") {
>> "^w" {"$_ starts with letter 'w'"; break}
>> "^\w+$" {"$_ starts with another letter"}
>> }
>>
word starts with letter 'w'

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

Продолжение: Regex

комментариев 10 to “Регулярные выражения – Switch”

  1. abigor Says:

    Про последнее, спасибо, догадывался, что так и есть, но лень было спросить

  2. grinder Says:

    Хорошая статья. Только Еденица = Единица, а то глаза режет🙂

  3. Юрий Says:

    Спасибо за статью, это дело будет и приятней и читабельней последовательных foreach-ей. Хотя возможно существует способ и в пределах одного тела foreach указать несколько наборов к примеру для -replace, просто я не ведаю, как именно? Если резделять точкой с запятой, то получается в порядке очереди, что лично меня, до ознакомления с вышеразмещенным постом, печалило необычайно.

    • Xaegr Says:

      Об этом речь?
      «test»,»etc» | foreach { $_ -replace «t»,»T» -replace «e»,»E» }

  4. pan_2@LJ Says:

    Василий, я правильно понимаю что Вы были на TechDays?
    Или меня всё-таки проглючило? =)

  5. Скрипт поиска файлов-писем (почтовых сообщений) по полю “Subject” (“Тема”). Дубль два или работа над ошибками « ShS's Blog Says:

    […] же  можно «реабилитировать» и оператор Switch😉 Надо только вспомнить, о том, что помимо оператора […]

  6. ITband.ru » Регулярные выражения в Windows PowerShell Says:

    […] опубликована в блоге https://xaegr.wordpress.com – 1, 2, 3, 4, 5, 6, 7, 8, […]


Обсуждение закрыто.

%d такие блоггеры, как: