Ну чтож, пора новогодних каникул давно закончилась, и мне стало уже тяжело находить отмазки на вопросы о продолжении серии
Так как времени с момента предыдущего поста прошло уже немало времени, да и для тех кто натолкнулся на этот пост случайно – вот ссылки на посты которые рекомендуется прочитать сначала: 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]
Маленькая такая “новость”
Недавно натолкнулся вот на этот
Итак, подведём итоги этого года
Нет, сегодня речь не пойдет о вооруженных людях в черных масках
Продолжаем разговор о регулярных выражениях. В