PowerShell и регулярные выражения (часть 3). Больше или равно powershell


Могучий Шелл. Шпаргалка по PowerShell. Часть 1.

PowerShell на мой взгляд это идеальный инструмент для автоматизации абсолютно любых задач. Его можно изучать бесконечно и находить в нем все новые и новые возможности. Почти все продукты MS начиная с 2007 года поддерживают управление настройку и администрирование через PowerShell, что дает практически нереальные возможности в их администрировании и управлении. Это пост создан с целью иметь под рукой самые полезные скрипты и команды. Для тех кто совсем не знаком  с этим чудесным инструментом рекомендую видео . С чего же начинается PowerShell ? Чтобы начать пользоваться скриптами локально необходимо установить политику выполнения сценариев в  RemoteSigned Для этого достаточно выполнить команду Set-ExecutionPolicy RemoteSigned После этого можно спокойно пользоваться скриптами созданными локально Пару слов о том как устроен PowerShell  1.Каждая команда состоит из 2х частей ГЛАГОЛ (Get , Set, Add, Remove, Invoke , Start , Stop и тд  полный список Get-Verb)+ СУЩЕСТВИТЕЛЬНОЕ (Command , Service, Process , PSDrive  , ExecutionPolicy  ) =   Get-Command Более полную информацию о любом командлете (встроенная команда PowerShell ) можно получить Get-Help -name Get-Command Полный список команд можно получить  командой 2.Псевдонимы команд (алиасы) Дают возможность пользоваться сокращенными привычными названиями команд  ls, dir,  kill , del  , copy, cls Полный список алиасов Переменные начинаются со знака $ ,  переменные создаются в момент присваивания им значения, тип определяется автоматически Типизированные переменные , можно указать конкретный тип для тех кто привык к языкам программирования чтобы избежать ошибок в коде. Переменные оболочки PowerShell $$ Содержит последнее слово (или знак) последней полученной оболочкой строки $? Показывает, успешно ли завершилась последняя операция $^ Первое слово (или знак) последней полученной оболочной строки $_ При использовании в блоках сценариев, фильтрах и инструкции Where содержит текущий объект конвейера $PSHome            Показывает имя каталога, в который установлен Windows PowerShell $Host    Содержит сведения о текущем узле $Args    Содержит массив параметров, передаваемых в функцию $Error   Содержит объекты, для которых возникла ошибка при обработке в командлете $ForEach             Обращается к итератору в цикле ForEach $Home Указывает домашний каталог пользователя Системные переменные среды Windows $env:OS    #получить значение конкретной переменной Результат любого командлета можно сохранить в переменной Полезная штука, позволяет передавать результаты одной команды на вход другой, формируя цепочку команд, достаточно соединить команды символом | Get-Service | where {$_.Name -like "*sql*"} 4.Горячие клавиши, комментарии TAB – самая часто используемая, авто дополнение команд Начните писать команду и нажмите TAB PowerShell сам предложит вам возможные варианты команд F7  - список введенных команд Up          Сканирование назад по истории команд. Down    Сканирование вперед по истории команд. Pg Up    Доступ первая команда в истории команд. Pg Dn    Доступ последнюю команду в истории команд. Комментарии помечаются символом # #закомментировать строку Блочный комментарий Сменить цвет текста в консоли write-host "Sample text" -foreground "magenta" Форматирование чисел, дат и тд -f 

"{0:N4}" -f  (3.14159265359)$t =(get-date)"{0:dd.MM.yy}" -f  $t

5.Оснастки (PSSnapin) Если вкратце это сборки .NET  в  виде DLL библиотек, могут использоваться для управления чем угодно от настроек компьютера до прикладных программ Sharepoint, Exchange, Sql Server    и тд.  Подробное видео тут Получить список встроенных оснасток Получить список всех команд в оснастке Get-Command –module  Microsoft.PowerShell.Diagnostics Как добавить оснастку в консоль (можно добавить только там где установлен сам Sharepoint) Add-PSSnapin Microsoft.SharePoint.PowerShell Модуль это набор команд Powershell , появились начиная с версии 2.0 представляют собой замену оснасток, более просты в управлении, нет необходимости в регистрации библиотек, можно легко переносить между разными компьютерами. Подробное видео тут Получить список доступных модулей Get-Module –ListAvailable Получить список всех команд в модуле Get-Command -Module sqlps Как добавить модуль в консоль Import-Module ActiveDirectory 7.Базовые конструкции, символы %, $_  и New-Object If (($someAttribute -eq $false) -or ($someAttribute -eq $Null)) -eq                         Равно (=)                           -ne                         не равно (<>) -gt                          Больше (>)        -ge                         Больше или равно (>=)              -lt                           Меньше (<)      -le                          Меньше или равно (<=)            -like                       Сравнение с учётом символа подстановки -notlike                Сравнение с учётом не соответствия символа подстановки -contains             Содержит ли значение слева значение справа -notcontains      Если значение слева не содержит значение справа, получим истину -match                 Использование регулярных выражений для поиска соответствия образцу -notmatch          Использование регулярных выражений для поиска несоответствия образцу           -replace               Заменяет часть или все значение слева от оператора -and                      Логическое и   -or                          Логическое или             -not                       Логическое не foreach ($item in Get-PSDrive) for ($i = 0; $i -lt 10; $i++) Сокращенный аналог ForEach,  символ % $_ текущий элемент конвейера dir c:\temp2 | % {$str = "temp_" + $_.Name; $str } Создать новый  объект COM или .NET

$ie = New-Object -COMObject InternetExplorer.Application$ie.Navigate2("www.microsoft.com")$ie.Visible = $True

Выбор, фильтрация и сортировка Get-WmiObject win32_service |  select Name, Status, State, PathName|  Where-Object -FilterScript {$_.Name -like 'a*'}| Sort-Object -Property State Группировка результатов dir c:\temp | sort-object -property extension | group-object -property extension Посмотреть все свойства  объекта Get-Service -name wuauserv | Select-Object -Property * Вычисляемые поля  @{} Get-Service -name wuauserv | Select-Object -Property Name, Status , @{name='Desc';expression={$_.displayname}} 7.Полезные команды Полный список команд с примерами смотреть тут Как разобраться с новой командой смотрим помощь Затем смотрим примеры get-help Get-PSProvider -examples Все дочерние элементы  dir или Get-Children $a| Where {$_.PSIsContainer -eq $false}| select Name, @{name='Size_MB';e={$_.length/1MB}} Get-PSDrive | export-csv c:\temp\drives.csv -encoding utf8 Экспорт данных из  SQL $SqlConnection = new-object System.Data.SqlClient.SqlConnection $SqlConnection.ConnectionString = "Server=server;Database=database;Integrated Security=True" $SqlCommand = $SqlConnection.CreateCommand() $SqlCommand.CommandText = "Select * from tmp_test" $DataAdapter = new-object System.Data.SqlClient.SqlDataAdapter $SqlCommand $dataset = new-object System.Data.Dataset $tblData = $dataset.Tables[0] $tblData | export-csv c:\temp\table.csv -encoding utf8 Использование объектов .net $reader = [System.IO.File]::OpenText("c:\test\Import.txt") $arg1 = "https://cs1-41v4.vk-cdn.net/p7/407880aed25a77.mp3?extra=ZGdmt6lQkZ_APrCSiVS…dXexkP8RojEaEtgIWVJmsnnG0qOfJQnoe3khUMSg2D_ejsYUXwsp4h0x21yhzno5vAf3BYMfOY" $arg2 =  "C:\temp\SampleAudio.mp3" $p = New-Object System.Net.WebClient $p.DownloadFile($arg1,$arg2) Работа с реестром Set-Location -Path hklm:\SOFTWARE\Microsoft\Windows\CurrentVersion Get-ItemProperty -Path .  | out-file c:\temp\odbc.txt -width 200 Отправка писем $objMailClient = new-object Net.Mail.SmtpClient -arg "mailserver.example.com" $objMessage = new-object Net.Mail.MailMessage("[email protected]","[email protected]", "Subject", "Here is some email") $objAttach = new-object Net.Mail.Attachment("c:\\demo.txt") $objMessage.Attachments.Add($objAttach) $objMailClient.Send($objMessage)

Парсинг XML файлов и подготовка запросов SQL$folderPath= "C:\Shared\BR_Playlist\1\"$HouseIds= @()foreach ($item in dir $folderPath){$xmlFilePath = $folderPath + $item.Name[xml] $xmlContent = [xml] (Get-Content -Path $xmlFilePath)#Write-Host $item.Nameforeach( $event in $xmlContent.playlist.program.event ) {     #Write-Host $event.housenumber    $HouseIds+=$event.housenumber}}#{$_}  $HouseIds | sort-object | Get-Unique | Select-Object   @{Name="Comnd";Expression={"Select '"+$_+"' as evnt UNION ALL"  }}

Импорт собственной DLL

$assembly = [Reflection.Assembly]::LoadFile("c:\path\file.dll")

$instance = New-Object Class.Of.Assembly

$instance.Property1 = $variable1

$result = $instance.function()

Очень много скриптов powershell тут

eazybi.blogspot.com

PowerShell и регулярные выражения (часть 3)

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

Альтернатива

Символ | (вертикальная черта) в регулярных выражениях означает «или» и позволяет выбрать один из нескольких вариантов. К примеру, конструкция a|b|c означает ″или a или b или c″, где  a b и c являются альтернативами. Если взять выражение, рассмотренное в первой части:

Get-Service | where {$_.Name -match ″v[ds]s″}

то с помощью альтернатив его можно записать так:

Get-Service | where {$_.Name -match ″v(d|s)s″}

или так:

Get-Service | where {$_.Name -match ″vds|vss″}

Примечание. Не стоит сравнивать символьные классы и альтернативы. Хотя в предыдущем примере конструкции [ds] и (d|s) выдают одинаковый результат, в общем случае это совершенно разные вещи. Символьный класс описывает только один символ, тогда как в качестве альтернативы может выступать регулярное выражение неограниченной длины и сложности.

 

Хотя данная статья посвящена регулярным выражениям, не стоит слишком на них зацикливаться. К примеру конструкцию выбора можно организовать средствами PowerShell, используя оператор -or (или). Так предыдущее выражение можно записать следующим образом:

Get-Service | where {$_.Name -match ″vds″ -or $_.Name -match ″vss″}

 

Важный момент при использовании альтернатив — это их порядок. Для примера возьмем выражение:

″one, two, three″ -match ″(one)|(two)|(three)″

Если опустить тонкости, то проверка производится так — берется первое слово в строке (one) и сравнивается по очереди с каждой из альтернатив (one, two и three). Если совпадение, как в нашем примере, найдено, то выдается положительный результат, иначе процесс повторяется для следующего слова (two)  и так до нахождения соответствия или окончания строки. Поскольку в нашем примере слово one стоит в начале строки и альтернатива one находится на первом месте, то поиск завершается максимально быстро. Теперь возьмем такое выражение:

″one, two, three″ -match ″(three)|(two)|(one)″

Как видите, теперь поиск пойдет несколько медленнее, поскольку one сравнивается сначала с three, потом с two и только затем с one. А если взять такое выражение:

″one, two, three″ -match ″(five)|(four)|(three)″

то процесс будет идти еще дольше, поскольку сначала пойдет сравнение one с five, four и three, затем то-же для two уже затем для three.

 

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

Альтернатива на основании условия

Альтернативу можно организовать так, что выбор между альтернативными вариантами будет осуществляться в зависимости от некоторого условия. Так конструкция (?if (then|else)) означает, что сначала проверяется регулярное выражение if, если оно истинно — то выполняется проверка выражения then, иначе проверяется выражение else.

Для примера возьмем выражение, которое ищет в строке IP или Mac-адрес:

″192.168.0.1″ -match «(?(^\d{1,3}\.)((\d{1,3}\.){3}\d{1,3})|(\w+-){5}(\w+))

Сначала идет условие (?(^\d{1,3}\.), в котором проверяется наличие в начале строки от 1 до 3 цифр и точки (начало IP-адреса). Если совпадение найдено, то ищем IP-адрес с помощью выражения (\d{1,3}\.){3}\d{1,3}), иначе ищем Mac-адрес выражением (\w+-){5}(\w+).

 

Примечание. Напомню, что IP представляет из себя 4 группы символов разделенных точкой, в каждой группе от 1 до 3 цифр (напр. 192.168.0.1). Mac-адрес состоит из 12 символов (букв или цифр), как правило сгруппированных по 2 и разделенных дефисом (напр. 1A-2B-3C-4D-5E-6F).

Альтернатива на основании захваченной группы

В качестве условия может выступать захваченная группа. Синтаксис выглядит как (?(name) then|else)) или (?(number) then|else)), где name и number — соответственно имя или номер захваченной группы. Если имя\номер группы соответствует захваченной группе то выполняется выражение then, иначе выполняется выражение else.

Немного изменим предыдущее выражение, в качестве условия используем именованную группу mac:

″1A-2B-3C-4D-5E-6F″ -match «(?<mac>^\w{2}-))(?(mac))(\w{2}-){5}\w{2}|(\d{1,3}\.?){4}″

Конструкция (?<mac>^\w{2}-) проверяет, что в начале строки идут 2 символа и дефис (начало Mac-адреса) и помещает результат в группу mac. Если группа есть, то выражение (\w{2}-){5}\w{2} ищет полный Mac-адрес, иначе используется выражение (\d{1,3}\.?){4} для поиска IP-адреса.

 

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

″1A-2B-3C-4D-5E-6F″ -match «(^\w{2}-))(?(1))(\w{2}-){5}\w{2}|(\d{1,3}\.?){4}″

Позиционная проверка

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

• Позитивная опережающая проверка (?=…) — должно совпасть справа;• Позитивная ретроспективная проверка (?<=…) — должно совпасть слева;• Негативная опережающая проверка (?!…) — не должно совпасть справа;• Негативная ретроспективная проверка (?<!…) — не должно совпасть слева.

Для примера используем позитивную опережающую проверку для поиска слова, справа от которого идет слово four:

″one two three four five″ -match ″(\b\w+)\s(?=four)\b″

А теперь с помощью позитивной ретроспективной проверки найдем слово, слева от которого есть слово two:

″one two three four five″ -match ″(?<=two)\s(\w+\b)″

 

Проверку можно ставить как до, так и после выражения, например так мы ищем слово, за которым стоит слово four, используя позитивную опережающую проверку:

″one two three four five″ -match ″(?=\b\w+\sfour)(\w+\b)″

 

В одном выражении может быть несколько проверок. Для примера найдем позицию в строке, слева от которой находится three, а справа four и поставим между ними дефис:

″one two three four five″ -replace ″\b(?<=three)\s(?=four\b)″,″-″

 

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

″100 rubles, 50 dollars, 20 pounds″ -match ″\b(?!\d+\srubles).?\s(\d+\s\w+\b)″

А так, применив негативную ретроспективную проверку, мы найдем словосочетание, после которого нет слова pounds:

″100 rubles, 50 dollars, 20 pounds″ -match ″\b(?<!\d+\spounds).?\s(\d+\s\w+\b)″

 

Использовать позиционные проверки можно множеством различных вариантов. К примеру, следующее выражение выбирает строки, не начинающиеся на un:

″unique″,″unit″,″you″ -match ″\b(?!un)\w+\b″

Практический пример

Сделать так, чтобы регулярное выражение совпало с тем, чем нужно — это довольно просто. Гораздо сложнее сделать так, чтобы выражение не совпадало с тем, с чем не нужно, т.е. исключить все нежелательные совпадения. В качестве примера возьмем текстовый файл, и попробуем выбрать из него строки, содержащие IP-адрес.

Для удобства поместим содержимое файла в переменную $ip и начнем поиск. Cначала попробуем такое выражение:

$ip | where {$_ -match ″[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*″}

Конструкцию [0-9] можно заменить на \d, получится чуть короче:

$ip | where {$_ -match ″\d*\.\d*\.\d*\.\d*″}

 

На первый взгляд вроде все верно, но в результате получаем не только нормальные IP-адреса, но и кучу непонятных значений. Здесь стоит вспомнить о том, что квантификатор * означает ″любое количество совпадений или отсутствие совпадений″, т.е.  в выражении \d*\.\d*\.\d*\.\d* необходимыми являются только точки, все остальное необязательно.

Уберем необязательность, заменив квантификатор * на +, и на всякий случай обозначим начало и конец искомой строки:

$ip | where {$_ -match ″^\d+\.\d+\.\d+\.\d+$″}

 

Совсем неподходящие строки типа …? отсеялись, но все равно в результате полно мусора. Поскольку каждое число может содержать от 1 до 3 цифр, попробуем более точно ограничить количество символов, заменив квантификатор + на {1,3}:

$ip | where {$_ -match ″^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$″}

И еще немного сократим выражение:

$ip | where {$_ -match ″^(\d{1,3}\.){3}\d{1,3}$″}

или так:

$ip | where {$_ -match ″^(\d{1,3}\.?){4}$″}

 

Получившееся выражение уже вполне можно использовать для поиска IP, однако оно все еще пропускает неправильные варианты типа 521.467.09.11 или 999.999.999.999. На этом этапе можно остановиться, признав некоторую неточность выражения, а можно пойти по пути уточнения, что приведет к усложнению выражения. Можно сказать что это компромисс между простотой и точностью.

Для дальнейшего уточнения вспоминаем, что в IP-адресе могут быть числа от 0 до 255, поэтому нам необходимо проследить за тем, какие цифры допускаются в числе и в каких позициях они находятся. Пойдем по порядку:

• Если число состоит из 1 или 2 цифр, то максимальное возможное число это 99, т.е принадлежность к диапазону 0-255 проверять не нужно. Проверить это условие можно выражением \d|\d\d;•  Если число начинается с 0 или 1, то оно заведомо принадлежит к интервалу 0-199 и тоже не нуждается в проверке. Суммируя с первым условием, получаем выражение \d|\d\d|[01]\d\d;• Число, состоящее из трех цифр и начинающееся с 2 допустимо в том случае, если оно не больше 255, следовательно, если вторая цифра меньше 5, то число правильное, а если равна 5, то третья цифра должна быть меньше 6. Выразить это можно как 2[0-4]\d|25[0-5].

Объединив все требования, получаем выражение \d|\d\d|[01]\d\d|2[0-4]\d|25[0-5]. Сократим его, объединив первые три альтернативы, в результате получится выражение [01]?\d\d?|2[0-4]|25[0-5], которое описывает число от 0 до 255. Остается заключить его в скобки и подставить в выражение вместо \d{1,3}:

$ip | where {$_ -match ″^(([01]?\d\d?|2[0-4]|25[0-5])\.){3}([01]?\d\d?|2[0-4]|25[0-5])$″}

 

Результат доcтаточно точен, но в нем равно присутствует вариант из одних нулей. Для исключения этого варианта вставим проверку:

$ip | where {$_ -match ″^(?!(0+\.?){4})(([01]?\d\d?|2[0-4]|25[0-5])\.){3}([01]?\d\d?|2[0-4]|25[0-5])$″}

 

Вот теперь в результате только валидные IP-адреса, однако выражение получилось довольно сложным. Стоит ли стремиться за точностью и усложнять выражение или пойти на компромисс — все зависит от конкретной ситуации.

Заключение

В в своих статьях я описал лишь базовые возможности регулярных выражений. На этом мои знания иссякли 🙂 поэтому для дальнейшего изучения можно зайти на MSDN, где есть целый раздел, посвященный регулярным выражениям —  .NET Framework Regular Expressions. Также в качестве справочника рекомендую «Regular Expressions Cookbook» издательства O′Reilly и книгу Дж. Фридла «Регулярные выражения», в которой очень подробно объясняются тонкости работы регулярных выражений.

windowsnotes.ru

Использование математических функций в PowerShell

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

 

А вот для более сложных математических операций придется задействовать статический класс [math]. В этот класс входит около 30 свойств и методов, с помощью которых можно производить различные математические действия. Для начала выведем эти методы командой:

[math] | Get-Member -Static

Ну а теперь рассмотрим их все по порядку.

Константы

Начнем с двух свойств, E и PI. Как вы наверное догадались, это математические константы. PI равно отношению длины окружности к длине её диаметра, E — основание натурального логарифма. Вывести их значение можно командой:

[math]::PI[math]::E

Степени, корни и логарифмы

Переходим к методам. Метод ::Pow(x,y) возводит число х в степень у, например:

[math]::Pow(3,2) возвращает 9

Метод ::Sqrt(x) вычисляет квадратный корень из числа x, например:

[math]::Sqrt(9) возвращает 3

 

Метод ::Exp(x) служит только для одного —  возведения в степень x числа E. Например так возведем E в квадрат:

[math]::Exp(2)

а так в куб:

[math]::Exp(3)

 

Продолжая тему числа E, рассмотрим еще парочку методов. Метод ::Log(x) вычисляет натуральный логарифм числа x (логарифм с основанием e), а метод ::Log10(x) — десятичный логарифм  (логарифм с основанием 10). Например:

[math]::Log(2)[math]::Log10(2)

Округление

Округление — довольно часто встречающаяся операция. Метод ::Round(x,y) округляет число x, а y задает нужное количество знаков после запятой. Например:

[math]::Round(1234.5678, 2) возвращает 1234.56[math]::Round(1234.5678, 0) возвращает 1234

 

Обратите внимание на правила округления:

[math]::Round(12.345, 2) возвращает 12.34[math]::Round(12.346, 2) возвращает 12.35

 

Метод ::Truncate(x) также можно использовать для округления числа x, однако в отличие от предыдущего метода округление производится очень грубо — путем отбрасывания всех знаков после запятой. Например:

[math]::Truncate(1.2) возвращает 1[math]::Truncate(1.8) возвращает 1[math]::Truncate(-1.2) возвращает -1[math]::Truncate(-1.8) возвращает -1

 

И еще два метода округления. Метод ::Ceiling(x) округляет число х в большую сторону до ближайшего целого значения. Например:

[math]::Ceiling(1.2) возвращает 2[math]::Ceiling(1.8) возвращает 2[math]::Ceiling(-1.2) возвращает -1[math]::Ceiling(-1.8) возвращает -1

 

Метод ::Floor(x) также округляет число до ближайшего целого значения, но в меньшую сторону. Например:

[math]::Floor(1.2) возвращает 1[math]::Floor(1.8) возвращает 1[math]::Floor(-1.2) возвращает -2[math]::Floor(-1.8) возвращает -2

Сравнение

Есть в классе [math] пара методов для сравнения. К примеру метод ::Min(x,y) возвращает наименьшее, а метод ::Max(x,y) — наибольшее из двух чисел:

[math]::Min(1,2) возвращает 1[math]::Max(1,2) возвращает 2[math]::Min(1,-2) возвращает -2

 

А метод ::Equals(x,y) сравнивает числа х и y и возвращает True, если числа ровны и False, если не ровны. Например:

[math]::Equals(1,2) возвращает False[math]::Equals(2,2) возвращает True

 

Важно помнить, что для сравнения x и у должны иметь один тип данных. К примерк, для оператора Equals 2 (int32) не равно 2.0 (double) или ″2″ (string):

[math]::Equals(2,2.0) возвращает False[math]::Equals(2,″2″) возвращает False

Абсолютное значение и знак числа

Метод ::Abs(x) возвращает абсолютное значение числа х, т.е. значение без учета знака. Например:

[math]::Abs(10) возвращает 10[math]::Abs(-10) возвращает 10

 

Метод ::Sign(x) возвращает значение, определяющее знак числа х — 1 если число положительное, -1 если число отрицательное и 0, если x равен 0. Например:

[math]::Sign(20) возвращает 1[math]::Sign(0) возвращает 0[math]::Sign(-10) возвращает -1

 

В качестве x можно передавать не только отдельные числа, но и выражения:

[math]::Sign(10-15) возвращает -1[math]::Sign(-1*2+2) возвращает 0

Разное

Теперь рассмотрим некоторые специфические функции, которые скорее всего вам никогда не понадобятся 🙂

Функция ::IEEERemainder(x,y) возвращает остаток от деления X / Y, однако делает это несколько необычным образом. Так при делении X / Y остаток вычисляется по формуле X — (Y * Q), где Q является частным от деления X / Y, округленным до ближайшего целого числа. Если X / Y находятся на равном расстоянии от двух целых чисел, то выбирается четное. Поскольку значение Y * Q может быть больше чем X, остаток может принимать как положительные, так и отрицательные значения. Например:

[math]::IEEERemainder(19,6) возвращает 1[math]::IEEERemainder(18,6) возвращает 0[math]::IEEERemainder(17,6) возвращает -1

Другими словами, IEEERemainder возвращает минимальное число, которое необходимо добавит или вычесть из делимого X, чтобы сделать его кратным делителю Y.

 

Метод ::BigMul предназначен для умножения двух 32-битных чисел. Результат умножения возвращается в виде 64-битного числа. Использовать этот метод стоит в том случае, если для результата вам не хватает 32-битов.

 

Метод ::DivRem(x,y,[ref]$R) вычисляет результат деления X/Y и возвращает остаток от деления в выходном параметре ($R). Обратите внимание, что переменная $R должна быть определена заранее:

$R = 0[math]::DivRem(20,3,[ref]$R) возвращает частное 6$R возвращает остаток от деления 2

Тригонометрические функции

Ну и в завершение тригонометрические функции. Наврядли вы будете использовать их в своих скриптах, поэтому привожу их исключительно для общего развития. Напомню, что по умолчанию эти функции вычисляются в радианах, поэтому для перевода в градусы необходимо использовать конструкцию (x/180*Pi). Например вычислим синус 90º:

$Pi = [math]::PI[math]::Sin(90/180 * $Pi)

косинус 180º:

[math]::Sin(180/180 * $Pi)

или тангенс 45º:

[math]::Tan(45/180 * $Pi)

 

Обратные тригонометрические функции. Они также вычисляются в радианах, для преобразования в градусы результат надо умножить на 180/Pi. Для примера вычислим арксинус 1 (угол, синус которого равен 1):

[math]::Asin(1)*180/$Pi

арктангенс 0:

[math]::Atan(0)*180/$Pi

и арккосинус -1:

[math]::Acos(-1)*180/$Pi

 

Ну вот, основные математические функции PowerShell мы рассмотрели. А более подробно познакомится со свойствами и методами класса [math] можно на MSDN.

windowsnotes.ru

Использование в PowerShell Where, Where-Object, ?

PS C:\> Get-ADUser -Filter * | Get-Member

 

 

   TypeName: Microsoft.ActiveDirectory.Management.ADUser

 

Name              MemberType            Definition

----              ----------            ----------

Contains          Method                bool Contains(string propertyName)

Equals            Method                bool Equals(System.Object obj)

GetEnumerator     Method                System.Collections.IDictionaryEnumerator GetEnumerator()

GetHashCode       Method                int GetHashCode()

GetType           Method                type GetType()

ToString          Method                string ToString()

Item              ParameterizedProperty Microsoft.ActiveDirectory.Management.ADPropertyValueCollection Item(string p...

DistinguishedName Property              System.String DistinguishedName {get;set;}

Enabled           Property              System.Boolean Enabled {get;set;}

GivenName         Property              System.String GivenName {get;set;}

Name              Property              System.String Name {get;}

ObjectClass       Property              System.String ObjectClass {get;set;}

ObjectGUID        Property              System.Nullable`1[[System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, ...

SamAccountName    Property              System.String SamAccountName {get;set;}

SID               Property              System.Security.Principal.SecurityIdentifier SID {get;set;}

Surname           Property              System.String Surname {get;set;}

UserPrincipalName Property              System.String UserPrincipalName {get;set;}

 

 

PS C:\> Get-ADUser -Filter * -Properties * | Get-Member

 

 

   TypeName: Microsoft.ActiveDirectory.Management.ADUser

 

Name                                 MemberType            Definition

----                                 ----------            ----------

Contains                             Method                bool Contains(string propertyName)

Equals                               Method                bool Equals(System.Object obj)

GetEnumerator                        Method                System.Collections.IDictionaryEnumerator GetEnumerator()

GetHashCode                          Method                int GetHashCode()

GetType                              Method                type GetType()

ToString                             Method                string ToString()

Item                                 ParameterizedProperty Microsoft.ActiveDirectory.Management.ADPropertyValueColle...

AccountExpirationDate                Property              System.DateTime AccountExpirationDate {get;set;}

accountExpires                       Property              System.Int64 accountExpires {get;set;}

AccountLockoutTime                   Property              System.DateTime AccountLockoutTime {get;set;}

AccountNotDelegated                  Property              System.Boolean AccountNotDelegated {get;set;}

adminCount                           Property              System.Int32 adminCount {get;set;}

AllowReversiblePasswordEncryption    Property              System.Boolean AllowReversiblePasswordEncryption {get;set;}

AuthenticationPolicy                 Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...

AuthenticationPolicySilo             Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...

BadLogonCount                        Property              System.Int32 BadLogonCount {get;}

badPasswordTime                      Property              System.Int64 badPasswordTime {get;set;}

badPwdCount                          Property              System.Int32 badPwdCount {get;set;}

CannotChangePassword                 Property              System.Boolean CannotChangePassword {get;set;}

CanonicalName                        Property              System.String CanonicalName {get;}

Certificates                         Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...

City                                 Property              System.String City {get;set;}

CN                                   Property              System.String CN {get;}

codePage                             Property              System.Int32 codePage {get;set;}

Company                              Property              System.String Company {get;set;}

CompoundIdentitySupported            Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...

Country                              Property              System.String Country {get;set;}

countryCode                          Property              System.Int32 countryCode {get;set;}

Created                              Property              System.DateTime Created {get;}

createTimeStamp                      Property              System.DateTime createTimeStamp {get;}

Deleted                              Property              System.Boolean Deleted {get;}

Department                           Property              System.String Department {get;set;}

Description                          Property              System.String Description {get;set;}

DisplayName                          Property              System.String DisplayName {get;set;}

DistinguishedName                    Property              System.String DistinguishedName {get;set;}

Division                             Property              System.String Division {get;set;}

DoesNotRequirePreAuth                Property              System.Boolean DoesNotRequirePreAuth {get;set;}

dSCorePropagationData                Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...

EmailAddress                         Property              System.String EmailAddress {get;set;}

EmployeeID                           Property              System.String EmployeeID {get;set;}

EmployeeNumber                       Property              System.String EmployeeNumber {get;set;}

Enabled                              Property              System.Boolean Enabled {get;set;}

Fax                                  Property              System.String Fax {get;set;}

GivenName                            Property              System.String GivenName {get;set;}

HomeDirectory                        Property              System.String HomeDirectory {get;set;}

HomedirRequired                      Property              System.Boolean HomedirRequired {get;set;}

HomeDrive                            Property              System.String HomeDrive {get;set;}

HomePage                             Property              System.String HomePage {get;set;}

HomePhone                            Property              System.String HomePhone {get;set;}

Initials                             Property              System.String Initials {get;set;}

instanceType                         Property              System.Int32 instanceType {get;}

isCriticalSystemObject               Property              System.Boolean isCriticalSystemObject {get;set;}

isDeleted                            Property              System.Boolean isDeleted {get;}

KerberosEncryptionType               Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...

LastBadPasswordAttempt               Property              System.DateTime LastBadPasswordAttempt {get;}

LastKnownParent                      Property              System.String LastKnownParent {get;}

lastLogoff                           Property              System.Int64 lastLogoff {get;set;}

lastLogon                            Property              System.Int64 lastLogon {get;set;}

LastLogonDate                        Property              System.DateTime LastLogonDate {get;}

lastLogonTimestamp                   Property              System.Int64 lastLogonTimestamp {get;set;}

LockedOut                            Property              System.Boolean LockedOut {get;set;}

logonCount                           Property              System.Int32 logonCount {get;set;}

logonHours                           Property              System.Byte[] logonHours {get;set;}

LogonWorkstations                    Property              System.String LogonWorkstations {get;set;}

Manager                              Property              System.String Manager {get;set;}

MemberOf                             Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...

MNSLogonAccount                      Property              System.Boolean MNSLogonAccount {get;set;}

MobilePhone                          Property              System.String MobilePhone {get;set;}

Modified                             Property              System.DateTime Modified {get;}

modifyTimeStamp                      Property              System.DateTime modifyTimeStamp {get;}

msDS-User-Account-Control-Computed   Property              System.Int32 msDS-User-Account-Control-Computed {get;}

Name                                 Property              System.String Name {get;}

nTSecurityDescriptor                 Property              System.DirectoryServices.ActiveDirectorySecurity nTSecuri...

ObjectCategory                       Property              System.String ObjectCategory {get;}

ObjectClass                          Property              System.String ObjectClass {get;set;}

ObjectGUID                           Property              System.Nullable`1[[System.Guid, mscorlib, Version=4.0.0.0...

objectSid                            Property              System.Security.Principal.SecurityIdentifier objectSid {g...

Office                               Property              System.String Office {get;set;}

OfficePhone                          Property              System.String OfficePhone {get;set;}

Organization                         Property              System.String Organization {get;set;}

OtherName                            Property              System.String OtherName {get;set;}

PasswordExpired                      Property              System.Boolean PasswordExpired {get;set;}

PasswordLastSet                      Property              System.DateTime PasswordLastSet {get;set;}

PasswordNeverExpires                 Property              System.Boolean PasswordNeverExpires {get;set;}

PasswordNotRequired                  Property              System.Boolean PasswordNotRequired {get;

get-powershell.ru

PowerShell и регулярные выражения (часть 2)

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

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

Как вы помните из предыдущей части, с помощью символьных классов можно описать то, какие именно символы надо искать, но нельзя указать их количество. Так символьный класс [a-z] описывает одну любую букву латинского алфавита, соответственно для описания большего количества букв потребуется конструкция [a-z][a-z]…[a-z]. Для примера выведем системные процессы с именем, состоящим из трех символов:

Get-Process | where {$_.ProcessName -match ″^[a-z][a-z][a-z]$″}

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

Get-Process | where {$_.ProcessName -match ″^[a-z]{3}$″}

 

Указывать точное число вовсе необязательно. Квантификаторы позволяют указывать диапазон в формате {x,y}, где х — минимально необходимое, а у — максимально возможное количество символов. Например выведем системные процессы с именем, содержащие в названии от 1 до 4 символов:

Get-Process | where {$_.ProcessName -match ″^[a-z]{1,4}$″}

 

Максимальное значение можно опустить, задав только минимальное, например {3, } означает ″3 и более символов″. Для наиболее общих квантификаторов есть сокращенное написание:

+ (плюс) — один или более символов, эквивалент {1, };* (звездочка) — любое количество символов или полное их отсутствие, эквивалент {0, };? (знак вопроса) — один символ или отсутствие символа, эквивалент {0,1}.

Обратите внимание, что, в отличие от подстановочных символов, квантификаторы в регулярных выражениях не используются сами по себе, а всегда применяются к символу или группе, например (.?) — один любой символ, (.*) — любое количество любых символов. Следующей командой выведем процессы с именем, начинающемся и заканчивающиеся на s, между которыми может быть любое количество символов:

Get-Process | where {$_.ProcessName -match ″^s.*s$″}

 

И еще, стоит помнить о необязательности квантификаторов, у которых в качестве минимального значения стоит ноль (напр. ? и *).  Это значит, что регулярные выражения с их использованием для положительного результата не нуждаются хотя-бы в одном совпадении, они совпадают даже при отсутствии символов. Например выражения ″.?″ , ″.*″ или ″[a-z]*″ совпадают с чем угодно, включая пустую строку.

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

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

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

$files = Get-ChildItem C:\Files\PS Books$files[1].Name

А теперь возьмем полученное имя и поменяем в нем ″PowerShell″ на ″CMD″:

$files[1].Name -replace ″PowerShell″, ″CMD″

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

$files[1].Name -replace ″PowerShell″

 

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

$files[1].Name -split ″\s″

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

$files[1].Name -split ″\s″, 2

 

Примечание. Так же как и match, операторы replace и split не зависят от регистра символов. Для этого у них имеются регистрозависимые версии creplace и csplit.

Лень и жадность

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

″Greedy and Lazy Quantifiers″ -replace ″L.*″

Как видите, в данном случае квантификатор * отработал максимуму, захватив часть строки Lazy Quantifiers, т.е. все что следует после L и до конца строки. Поскольку такой подход не всегда приемлем, существует возможность ограничить квантификатор необходимым минимумом. Для этого есть ″ленивые″ версии квантификаторов, получаемые с помощью добавления вопросительного знака, напр. *?, +?, ??, {1,10}?. Немного изменим предыдущую команду:

″Greedy and Lazy Quantifiers″ -replace ″L.*?″

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

″Greedy and Lazy Quantifiers″ -replace ″L.*?\s″

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

Захватывающие группы

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

″Test grouping in regular expressions.″ -match ″(\w+\s){4}(\w+)\.$″

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

″Test grouping in regular expressions.″ -match ″(\w+)\s(\w+)\.$″

Если теперь вывести содержимое переменной $Matches, то под индексом 0 там находится вся совпавшая строка целиком, под индексом 1 — содержимое первой группы, под индексом 2 — содержимое второй группы и т.д. Что особенно важно, можно обращаться к каждому элементу отдельно, например:

$Matches[2]

Это позволяет не просто найти, но и извлечь полученный результат.

 

Группы могут быть вложенными одна в другую, например так:

″Test grouping in regular expressions.″ -match ″((\w+)\s(\w+))\.$″

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

 

При необходимости группе можно присвоить имя, чтобы было удобнее к ней обращаться. Именованные группы имеют синтаксис (?<name> subexpression) или (?’name’ subexpression), где name — имя группы, а subexpression — регулярное выражение. Имя группы не должно начинаться с цифры и содержать знаков пунктуации. Например, предыдущее выражение с использованием именованных групп будет выглядеть так:

″Test grouping in regular expressions.″ -match ″(?’first’\w+)\s(?’second’\w+)\.$″

Обращаться к именованным группам можно как по их номеру, так и по имени, например:

$Matches[‘first’]

или так:

$Matches.first

Обратные ссылки

Еще одной особенностью групп является то, что внутри регулярного выражения на них можно ссылаться с помощью конструкций, называемых обратными ссылками (backreference). В некоторых случаях это очень удобно, например для поиска повторяющихся элементов в строке. Ссылаться на неименованные группы можно с помощью конструкции \n, где n является порядковым номером группы в регулярном выражении. Для примера найдем повторяющиеся слова в строке:

″Test grouping in regular regular expressions.″ -match ″(\w+)\s(\1)″

Здесь в первую группу попадает слово regular, ссылка на которое (\1) затем используется во второй группе.

 

Поскольку подобная запись используется не только в обратных ссылках, но и для обозначения восьмеричных escape-кодов, то существуют следующие правила:

• Выражения от \1 до \9 всегда интерпретируются как обратные ссылки, а не как восьмеричные числа;• Выражения от \10 и больше считаются обратными ссылками в том случае, если имеется обратная ссылка, соответствующая данному номеру. В противном случае выражение интерпретируется как восьмеричный код;• Если первая цифра многоразрядного выражения 8 или 9 (напр. \85), то выражение интерпретируется как литерал.

Избавиться от неоднозначности можно с помощью именованных ссылок типа \k<name> или \k’name’ , где name — имя именованной группы. Такие ссылки однозначно указывают на группу и их невозможно спутать с восьмеричными символами. С их помощью выражение изменится следующим образом:

″Test grouping in regular regular expressions.″ -match ″(?<first>\w+)\s(\k<first>)″

Незахватывающие группы

При использовании захватывающих групп на сохранение их содержимого тратится дополнительное время и ресурсы, что при обработке больших объемов данных может отрицательно сказаться на производительности. Поэтому, если группы нужны исключительно для группировки символов, а в захвате нет необходимости, то можно использовать ″незахватывающие″ группы. Эти группы получаются с помощью переключателя (?: ), например:

″Test grouping in regular expressions.″ -match ″(?:\w+\s)(\w+)\.$″

Как видно из примера, поскольку первая группа является незахватывающей, в переменную $Matches попало только содержимое второй группы.

Практический пример

И в завершение статьи небольшой пример из практики. Предположим, имеется лог веб-сервера IIS, из которого мне необходимо достать ответы сервера на запросы по адресу www.site.ru. Для удобства выгрузим содержимое файла в переменную, а затем посмотрим формат записи на примере одной из строк:

$file = Get-Content C:\Files\err.log $file[5]

Как видите, в строке идет имя сайта, а сразу за ним код ответа сервера. Выведем необходимую информацию такой командой:

$file | where {$_ -match ″(www\.site\.ru)\s([\d]{3})″} | foreach {$Matches[0]}

 

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

windowsnotes.ru

Ищем на диске самые большие файлы с помощью PowerShell

Желая найти на диске самые большие файлы, пользователи чаще всего прибегают к помощи сторонних утилит, а ведь эту операцию можно выполнить средствами самой Windows. Нет, не Проводника, его возможности в этом плане ограничены, а командной строки PowerShell. За вывод содержимого каталогов в PowerShell отвечает командлет Get-ChildItem (GCi), его то как раз мы и будем использовать.

При необходимости вы можете вывести список всех файлов на диске, но это вряд ли вам понадобится, ведь цель иная — найти именно самые большие файлы, а поэтому ограничимся для примера 20-ю объектами.

Запускаем консоль PowerShell и выполняем такую команду:

Get-ChildItem D:\ -r | sort -descending -property length | sеlect -first 20 name, Length

Get-ChildItem D:\ -r | sort -descending -property length | sеlect -first 20 name, Length

Разберем команду.

В первой ее части указано, что поиск нужно производить на диске D с применением рекурсии, последнюю задает ключ -r. Второй частью команды (sort) мы сортируем файлы по размеру, начиная с самого большого, наконец, третьей частью команды (sеlect) производим выборку, оставляя только первые 20 объектов. Параметр Length в данном случае выводит размер файлов в байтах.

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

Для этого добавляем в конец цепочки команд такую строку:

@{Name="Мб";Expression={[Math]::round($_.length / 1MB, 2)}}

@{Name="Мб";Expression={[Math]::round($_.length / 1MB, 2)}}

Если же после ключа name добавить еще ключ DirectoryName и всё это передать через прямой слеш командлету Out-GridView.

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

В примере выше мы производили поиск на диске D, однако, если вы станете искать на системном томе, то более чем наверняка получите ошибку «Отказано в доступе по пути…».

Хотя сведения всё равно получите. Причина ошибки заключается в отсутствии прав доступа к некоторым системным папкам, она вылетит даже в том случае, даже если запустите PowerShell с правами администратора.

Чтобы сообщения об ошибках не портили вид, можете отключить их вывод, добавив к первой части команды сразу после ключа r ключ -ErrorAction SilentlyContinue.

И еще один маленький нюанс.

Если вы хотите включить в список объектов скрытые файлы, добавьте к первой части команды ключ -Force.

Вот, собственно и всё.

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

www.white-windows.ru