Команда Powershell Select-Object фильтрует вывод информации. Когда Where-Object выступает в качестве условий, через который проходит объект, Select-Object используется для фильтрации колонок и строк. Эта команда так же позволяет выводить дополнительные свойства, так как по умолчанию команды Powershell выводят не все свойства.
Описание и синтаксис
Если вы посмотрите свойства, который хранит объект, то увидите что их намного больше чем выводится по умолчанию:
Get-Service | Get-Member -MemberType *Property*
Для вывода всех свойств понадобится использовать Select-Object:
Get-Service -Name WinRM
Get-Service -Name WinRM | Select-Object -Property *
Знак '*' говорит, что нам нужно вывести все свойства. Вы так же можете заметить, что вывод в виде строки, а не таблицы. В некоторых случаях Powershell сам меняет формат отображения на список. Если нам нужна таблица добавьте Format-Table, но такой формат может быть сложно читаем:
Get-Service -Name WinRM | Select-Object -Property * | Format-Table
Что бы сделать вывод более читаемым можно указать только определенные колонки:
Get-Service -Name WinRM | Select-Object Name, RequiredServices | Format-Table
Параметр Property первый принимает значения и поэтому его не обязательно указывать.
Когда нужно вывести все колонки, кроме определенных можно использовать параметр ExcludeProperty:
Get-Service -Name WinRM | Select-Object * -ExcludeProperty ServiceName,Status,Name| ft
Алиасы
Эта команда имеет один алиас в виде Select:
Get-Process | Select Name, Path
Выражения и скрипты
Нам не обязательно указывать существующие свойства, можно использовать выражения. Один из самых очевидных примеров это то, что мы можем добавлять колонки с новыми значениями. Ниже пример где мы выводим еще одну колонку изменив число:
$num = @(1,2,3,4)
$num | select-object -Property {$PSItem+1}
$PSItem это значение, которое проходит через конвейер. Вы можете знать второй способ написания в виде "$_".
Колонка имеет имя по умолчанию, что бы изменить это разделим выражение на Label, где укажем имя и выражение Expression:
$num | select-object -Property @{Label="Значение + 1"; Expression={$PSItem+1}}
По сути мы имеем формат hashtable. Более наглядные примеры мы можем увидеть, когда нам нужно перевести один тип значений в другой.
Когда мы выполняем команду Get-Volume мы получаем список разделов, общее и свободное пространство. Добавим колонку, которая будет показывать процент свободного пространства:
Get-Volume | select -Property DriveLetter, @{Label='Free'; Expression = {[string]([int]($_.SizeRemaining/$_.Size*100)) + " %"}}
Выше уже упоминалось, что этот тип похож на hashtable. Мы можем вывести выражение в отдельную строку и просто вставить его в select:
$free = @{Label='Free'; Expression = {[string]([int]($_.SizeRemaining/$_.Size*100)) + " %"}}
Get-Volume | select -Property DriveLetter, $free
Такой же пример можно использовать и с процессами, где значения отображаются в Кб. На примере ниже я конвертирую в Мб:
Get-Process | Select-Object -Property Name, @{Label='WS(MB)'; Expression={$PSItem.WS/1Mb}}
Если вам нужны значения в GB или другом размере просто замените их в выражении. Если нужно округлить, можно использовать [int] так же как я это делал в предыдущем примере.
InputObject
Так же как и любые другие командлеты работающие через конвейер этот тоже имеет параметр InputObject. С помощью его мы можем использовать командлет без конвейера:
$data = Get-Host
Select-Object -Property Name -InputObject $data
Такое написание аналогично этому:
$data = Get-Host
$data | Select-Object -Property Name
ExpandProperty
Для примера рассмотрим ситуацию, где элемент хранит несколько значений. Это будет выглядеть так:
$hash = [pscustomobject]@{Type='array'; collection=@(1,2,3,4,5)}
$hash | Select-Object -Property $PSItem
Если мы хотим вывести все значения хранящиеся в Collection это нужно делать через метод ExpandProperty:
$hash = [pscustomobject]@{Type='array'; collection=@(1,2,3,4,5)}
$hash | Select-Object -Property Type -ExpandProperty collection
Дополнительные параметры
У нас есть два параметра, с помощью которых мы можем получать первые и последние элемент из объекта. Это параметры:
- First - получение элементов с начала;
- Last - получение элементов с конца.
Я не могу придумать пример без использования сортировки Powershell Sort-Object, поэтому пример ниже с ним. Мы возвращаем процесс, который имеет наибольшее значение PM:
Get-Process | Sort-Object WS -Descending | Select-Object -First 1
Есть возможность использовать индексы указав Index. В предыдущем примере мы получили первый элемент с использованием First, аналогичный пример с индексами:
Get-Process | Sort-Object WS -Descending | Select-Object -Index 0
Использование с условиями
Условия не совсем подходят для использования с Select, но это можно делать. Например у нас есть команда Get-NetTCPConnection, которая получает список сетевых сеансов с отображением портов и идентификаторов процессов:
Get-NetTCPConnection
С помощью условий заменим колонку RemotePort на имена протоколов:
$prot = @{Label='LocalPortName'; Expression={
if ($PSItem.LocalPort -eq 443){'HTTPS'}
elseif ($PSItem.LocalPort -eq 80){'HTTP'}
elseif ($PSItem.LocalPort -eq 22){'SSH'}
elseif ($PSItem.LocalPort -eq 53){'DNS'}
elseif ($PSItem.LocalPort -eq 389){'LDAP'}
elseif ($PSItem.LocalPort -eq 135){'LOC-SRV'}
}
}
Get-NetTCPConnection | Select-Object -Property LocalAddress,OwningProcess,LocalPort,$prot,RemotePort | Sort-Object -Descending LocalPortName | ft
Обратите внимание, что сортировка применяется после создания колонки, а не до (как это было показано в другом примере).
Логично было бы использовать условия в виде switch в Powershell. Аналогичный пример, но со switch:
$prot = @{Label='LocalPortName'; Expression={
switch($PSItem.LocalPort){
443 {'HTTPS'}
80 {'HTTP'}
22 {'SSH'}
53 {'DNS'}
389 {'LDAP'}
135 {'LOC-SRV'}
}
}
}
Get-NetTCPConnection | Select-Object -Property LocalAddress,OwningProcess,LocalPort,$prot,RemotePort | Sort-Object -Descending LocalPortName | ft
Работа с Where-Object
Как уже говорилось в начале статьи, where чаще применяется в качестве условий, а select фильтрует колонки, и может изменять значения. В какой последовательности использовать обе команды - зависит от разных случаев. Если мы еще точно не знаем какие колонки нам нужно вывести лучше использовать where первым:
Get-Package | where -Property Name -Like "*C++*" | select Version
Если бы мы изменили порядок, то у нас бы ничего не отобразилось:
Get-Package | select Version |where -Property Name -Like "*C++*"
Это связано с тем, что мы выполняем where для колонки, которой не существует (в select выбран только Version). Другие примеры вы можете посмотреть в статье Фильтрация через Where-Object в Powershell с примерами.
...
Подписывайтесь на наш Telegram канал
Теги: #powershell