Добавить объект where в табличную конструкцию?
Переименование заголовков с помощью "label", и я хотел бы отфильтровать последний "SpaceLeft". Это не работает правильно, хотя. Например:
Get-WmiObject win32_logicaldisk -ComputerName sfuslt167 -Filter "drivetype=3" |
Format-Table -Property deviceID,
@{label='freespace(GB)';expression={$_.freespace / 1GB -as [int]}},
@{label='Size(GB)';expression={$_.size / 1GB -as [int]}},
@{label='SpaceLeft';expression={$_.freespace / $_.size * 100}} |
Where-Object {$_.SpaceLeft -lt 10}
Результаты:
deviceID freespace(GB) Size(GB) SpaceLeft
-------- ------------- -------- ---------
C: 130 237 54.8893461475826
Это должно возвращаться ни с чем, так как значение в "SpaceLeft" больше 10, указанное в операторе WHERE, но возвращается с результатами. Почему это??
1 ответ
Lee_Dailey предоставил ключевой указатель в комментарии:
Для преобразования данных для дальнейшей программной обработки используйте
Select-Object
или другие методы преобразования данных, например, черезForEach-Object
,Только когда-либо использовать
Format-*
Командлеты для форматирования данных для отображения, как следует из их названия.- Большой эволюционный скачок PowerShell заключался в отправке объектов, а не текста через конвейер, и в то же время
Format-*
командлеты, такие какFormat-Table
слишком испуская объекты, эти объекты больше не представляют данные, но инструкции по форматированию для системы форматирования вывода PowerShell - они не служат никакой другой цели.
- Большой эволюционный скачок PowerShell заключался в отправке объектов, а не текста через конвейер, и в то же время
Поэтому просто заменив Format-Table
с Select-Object
решает вашу проблему:
Get-WmiObject win32_logicaldisk -ComputerName sfuslt167 -Filter "drivetype=3" |
Select-Object -Property deviceID,
@{label='freespace(GB)';expression={$_.freespace / 1GB -as [int]}},
@{label='Size(GB)';expression={$_.size / 1GB -as [int]}},
@{label='SpaceLeft';expression={$_.freespace / $_.size * 100}} |
Where-Object {$_.SpaceLeft -lt 10}
Однако общим для этих двух командлетов является способность принимать рассчитанные свойства на основе хеш-таблиц (@{ label = '...'; expression = { ... } }
), как и в вашем вопросе.
Что касается того, что на самом деле произошло в вашей попытке:
Вот упрощенный пример, используя Format-Table
:
PS> [pscustomobject] @{ freespace = 100; size = 1000 } |
Format-Table @{label='SpaceLeft'; expression={$_.freespace / $_.size * 100}}
SpaceLeft
---------
10
Это выглядит просто отлично - и это действительно цель - создать хорошее представление дисплея.
На самом деле, подставляя Select-Object
за Format-Table
Результаты на том же дисплее:
PS> [pscustomobject] @{ freespace = 100; size = 1000 } |
Select-Object @{ label='SpaceLeft'; expression={$_.freespace / $_.size * 100} }
SpaceLeft
---------
10
Причина в том, что когда вывод команды идет на дисплей, PowerShell неявно, за кулисами вызывает соответствующий Format-*
командлет, который в этом случае Format-Table
, Другими словами, приведенная выше команда эквивалентна следующей команде:
PS> [pscustomobject] @{ freespace = 100; size = 1000 } |
Select-Object @{label='SpaceLeft'; expression={$_.freespace / $_.size * 100}} |
Format-Table
SpaceLeft
---------
10
Для логики, что за Format-*
Командлет выбирается, когда, см. этот ответ.
Однако вместо (неявно) примененного Format-Table
, вы могли бы выбрать другой командлет форматирования, например Format-List
для отображения в стиле списка, в котором каждое свойство отображается в отдельной строке:
PS> [pscustomobject] @{ freespace = 100; size = 1000 } |
Select-Object @{label='SpaceLeft'; expression={$_.freespace / $_.size * 100}} |
Format-List
SpaceLeft : 10
Тем не менее, когда дело доходит до дальнейшей обработки, Select-Object
а также Format-Table
не созданы равными - только Select-Object
подходит:
Давайте посмотрим, какими свойствами обладают выходные объекты, используя Get-Member -Type Properties
сначала с Select-Object
:
PS> ([pscustomobject] @{ freespace = 100; size = 1000 } |
Select-Object @{label='SpaceLeft'; expression={$_.freespace / $_.size * 100}} |
Get-Member -Type Properties).Name
SpaceLeft
Как и ожидалось, выход имеет одно свойство с именем SpaceLeft
и это то, что ваш Where-Object
Вызов может работать.
С помощью Format-Table
вместо Select-Object
рассказывает другую историю:
PS> ([pscustomobject] @{ freespace = 100; size = 1000 } |
Format-Table @{label='SpaceLeft'; expression={$_.freespace / $_.size * 100}} |
Get-Member -Type Properties).Name
autosizeInfo
ClassId2e4f51ef21dd47e99d3c952918aff9cd
groupingEntry
pageFooterEntry
pageHeaderEntry
shapeInfo
ClassId2e4f51ef21dd47e99d3c952918aff9cd
groupingEntry
shapeInfo
ClassId2e4f51ef21dd47e99d3c952918aff9cd
formatEntryInfo
outOfBand
writeStream
ClassId2e4f51ef21dd47e99d3c952918aff9cd
groupingEntry
ClassId2e4f51ef21dd47e99d3c952918aff9cd
groupingEntry
Неважно, что конкретно представляют эти частично неизвестные свойства - все, что имеет значение, это:
Их единственная цель - интерпретировать систему форматирования вывода PowerShell.
Выбранные / рассчитанные свойства передаются
Format-Table
отсутствуют как таковые в выводе.- Вот почему ваш
Where-Object
звонок не работал как задумано:$_.SpaceLeft
ссылается на несуществующее свойство, поэтому выражение оценивается как$null
, а также$null -lt 10
всегда$true
,
- Вот почему ваш
Независимо от их вклада, Format-*
командлеты выводят экземпляры Microsoft.PowerShell.Commands.Internal.Format.*
типы, которые представляют инструкции форматирования.