PowerShell и регулярные выражения (часть 3). Больше или равно powershell
Могучий Шелл. Шпаргалка по PowerShell. Часть 1.
$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