Как определить тип объекта в PowerShell
Оглавление
1. Определение типа объекта в PowerShell
3. Получение типа объекта с помощью Get-Member
4. Проверка типов объектов с помощью операторов типа -is и -isnot
5. Как проверить тип элементов коллекции
6. Свойство .GetType().IsArray для проверки, является ли объект массивом
1. Определение типа объекта в PowerShell
В PowerShell нет специального инструмента (например, командлета или свойства) которое показывало бы тип объекта. Тем не менее, некоторые командлеты показывают тип объекта как часть их вывода, также тип объекта можно узнать с помощью .NET API.
Из-за различных подходов вывод может различаться и немного сбивать с толку.
Также ещё больше запутывает то, что некоторые объекты являются коллекциями, содержащими объекты различных типов — мы остановимся на этом в самом конце, в том числе рассмотрим способы перебора всех элементов коллекции и определение их типа.
Я покажу здесь несколько способов определения типа объекта в PowerShell и, возможно, вы сможете подобрать что-то подходящее под ваши задачи.
Для примеров в этой заметке мы будем определять тип переменных со следующим содержимым:
$a = 'pwsh.ru and Suay.site' # String $b = 456 # Number, Int $c = @{ Number = 1; Shape = "Square"; Color = "Blue"} # Hash-table $d = 22,5,10,8,12,9,80,'Suay.site','pwsh.ru' # Array $e = Get-ChildItem $f = Get-Date $g = Get-ChildItem | Get-Member
2. Определение типа объекта с помощью метода .GetType() (а также .GetType().Name и .GetType().FullName
Вы можете определить тип объекта с помощью его метода GetType():
$a.GetType() $b.GetType() $c.GetType() $d.GetType() $e.GetType() $f.GetType() $g.GetType()
Метод .GetType() предоставляет метаданные об объекте, такие как его имя, базовый тип, сборка, из которой он взят, и т. д.
Как можно увидеть, тип объекта указан в столбце Name. Но для массива указан тип «Object[]», что в целом правильно, но является слишком общей характеристикой. Зато в столбце BaseType можно увидеть упоминание массива.
Вы можете ограничиться выводом только поля Name, для этого используйте .GetType().Name. Например:
$a.GetType().Name $b.GetType().Name $c.GetType().Name $d.GetType().Name $e.GetType().Name $f.GetType().Name $g.GetType().Name
Возможно, в каких-то ситуациях вам больше подойдёт FullName:
$a.GetType().FullName $b.GetType().FullName $c.GetType().FullName $d.GetType().FullName $e.GetType().FullName $f.GetType().FullName $g.GetType().FullName
Как вы можете помнить, для массивов более точное определение типа данных содержится в свойстве BaseType, при желании, вы можете получить только имя BaseType добавив к вашего объекту .GetType().BaseType.Name:
$a.GetType().BaseType.Name $b.GetType().BaseType.Name $c.GetType().BaseType.Name $d.GetType().BaseType.Name $e.GetType().BaseType.Name $f.GetType().BaseType.Name $g.GetType().BaseType.Name
Документация о методе Object.GetType: https://learn.microsoft.com/en-us/dotnet/api/system.object.gettype
3. Получение типа объекта с помощью Get-Member
Get-Member в основном предназначен для получения информации о членах (свойствах и методах) объекта (или статических членах класса, если вы используете параметр -Static). Например:
$a | Get-Member
Обратите внимание на первую строку, которая начинается с «TypeName:». Вы можете получить только вывод TypeName с помощью следующей конструкции:
(OBJECT | Get-Member)[0].TypeName
В этой команде замените OBJECT на объект, чей тип вы хотите узнать.
Примеры:
($a | Get-Member)[0].TypeName ($b | Get-Member)[0].TypeName ($c | Get-Member)[0].TypeName ($d | Get-Member)[0].TypeName ($e | Get-Member)[0].TypeName ($f | Get-Member)[0].TypeName ($g | Get-Member)[0].TypeName
Мы получили более чёткое представление о некоторых объектах (что-то более чем «Object[]»), например:
- DateTime
- DirectoryInfo
- MemberDefinition
Но для массива мы получили тип «Int32», что является явной ошибкой. Имейте ввиду, что если вам нужна информация о членах объекта коллекции, вы должны использовать
Get-Member -InputObject $COLLECTION
вместо передачи объекта по конвейеру
$COLLECTION | Get-Member
потому что использование конвейера развернёт коллекцию, и вы получите членов элементов коллекции, а не членов самого объекта коллекции.
То есть попробуйте следующую конструкцию:
(Get-Member -InputObject OBJECT)[0].TypeName
В этой команде замените OBJECT на объект, чей тип вы хотите узнать.
Примеры:
(Get-Member -InputObject $a)[0].TypeName (Get-Member -InputObject $b)[0].TypeName (Get-Member -InputObject $c)[0].TypeName (Get-Member -InputObject $d)[0].TypeName (Get-Member -InputObject $e)[0].TypeName (Get-Member -InputObject $f)[0].TypeName (Get-Member -InputObject $g)[0].TypeName
Как можно увидеть, остался тип данных DateTime, а DirectoryInfo и MemberDefinition вновь обозначены как Object[]. Массивы тоже обозначены как Object[].
4. Проверка типов объектов с помощью операторов типа -is и -isnot
-is и -isnot относятся к операторам типа и к операторам сравнения.
Оператор -is возвращает TRUE, если входные данные являются экземпляром указанного типа .NET.
Оператор -isnot возвращает TRUE, если входные данные не являются экземпляром указанного типа .NET.
Примеры:
$a -is [String] True $d -is [Array] True $e -is [System.IO.DirectoryInfo] False $e[0] -is [System.IO.DirectoryInfo] True (get-date) -is [DateTime] True (get-date) -isnot [DateTime] False
Больше примеров смотрите по ссылкам:
- об операторах типа: https://powershell-7.ru/?p=838
- об операторах сравнения: https://powershell-7.ru/?p=729
5. Как проверить тип элементов коллекции
Надеюсь, вы не слишком запутались к этому моменту. Если нет, то мы продолжаем 🙂
Некоторые из объектов, тип которых мы хотим проверить, являются коллекциями. В приведённых выше командах они зачастую определялись как «Object[]» или массив. Но эти объекты могут содержать в себе элементы коллекции разных типов.
Чтобы перечислить элементы коллекции и проверить их типы, вы можете использовать следующую конструкцию:
OBJECT | ForEach-Object {$_.GetType().Name}
В этой команде замените OBJECT на объект, для которого вы хотите перебрать все элементы и узнать тип каждого из этих элементов.
Например:
$a | ForEach-Object {$_.GetType().Name}
В переменной $a находится только один элемент и это строка.
В переменной $d содержится массив, проверим его содержимое:
$d | ForEach-Object {$_.GetType().Name}
Пример вывода:
Int32 Int32 Int32 Int32 Int32 Int32 Int32 String String
То есть мы можем увидеть, что некоторые члены массива являются числами, а некоторые строками.
В переменной $e содержится результат выполнения комнадлета Get-ChildItem:
$e | ForEach-Object {$_.GetType().Name}
В этой коллекции два типа объектов:
- DirectoryInfo
- FileInfo
Рассмотренные чуть выше операторы типа (-is и -isnot) всегда работают с входным объектом целиком. То есть, если входной объект является коллекцией, тестируется тип коллекции, а не типы элементов коллекции. Именно поэтому различается вывод для $e (проверяется тип всей коллекции):
$e -is [System.IO.DirectoryInfo]
И для $e[0] (проверяется тип первого элемента коллекции):
$e[0] -is [System.IO.DirectoryInfo]
Но при желании вы также можете делать проверку с помощью -is и -isnot каждого элемента коллекции, например:
$e | ForEach-Object {$_ -is [System.IO.DirectoryInfo]}
6. Свойство .GetType().IsArray для проверки, является ли объект массивом
У метода .GetType() имеется свойство .IsArray, которое позволяет проверить, является ли объект массивом:
OBJECT.GetType().IsArray
В этой команде замените OBJECT на объект, который вы проверяете.
Примеры:
$a.GetType().IsArray False $b.GetType().IsArray False $c.GetType().IsArray False $d.GetType().IsArray True $e.GetType().IsArray True $f.GetType().IsArray False $g.GetType().IsArray True
Конечно же, имеется и много других способов проверить, является ли объект массивом или другим типом (строкой, числом, хеш-таблицей и так далее), свойство .GetType().IsArray здесь упоминается по той причине, что в этой заметке мы довольно много говорили о методе .GetType(). Если вас интересует, имеются ли свойства вроде .GetType().IsString, .GetType().IsInt и другие подобные, то ответ отрицательный — таких свойств нет.
Заключение
Итак, объект может состоять из одного элемента (быть строкой, числом, хеш-таблицей, объектом DateTime и прочее) или быть коллекцией, состоящей из нескольких элементов, зачастую разного типа.
Хеш-таблицы расцениваются как один объект и хранимые значения не перебираются с помощью ForEach-Object.
А массив расценивается как коллекция, элементы который можно перебрать с ForEach-Object.
Вывод командлета может быть как массивом, так и особым объектом — например, выводом Get-Date является один объект [DateTime].
Выводом командлета может быть также массив, состоящий из объектов. Например, вывод Get-ChildItem представляет собой массив объектов [System.IO.DirectoryInfo] и [System.IO.FileSystemInfo].
Связанные статьи:
- Как присвоить вывод командлета переменной и как использовать переменную с сохранённым выводом (80%)
- Основы работы с PowerShell в Linux [Руководство для начинающих] (50%)
- Подстановочные символы в PowerShell (50%)
- Операторы сравнения в PowerShell (50%)
- Регулярные выражения в PowerShell (50%)
- Как выводить данные без таблицы в PowerShell (RANDOM - 20%)