在表结构上添加一个where-对象?

2023-11-29

用“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}

Results:

deviceID freespace(GB) Size(GB)        SpaceLeft
-------- ------------- --------        ---------
C:                 130      237 54.8893461475826

这应该不会返回任何内容,因为“SpaceLeft”中的值大于 WHERE 语句中指定的 10,但它会返回结果。为什么是这样??


李戴利在评论中提供了关键指针:

  • To 转换数据为进一步的程序化处理, use Select-Object或其他数据转换方法,例如通过ForEach-Object.

  • 只曾经使用过Format-*cmdlet 至format data 用于展示,正如他们的名字所暗示的。

    • PowerShell 的伟大进化飞跃是发送objects而不是text通过管道,同时Format-*cmdlet 例如Format-Table也会发出对象,这些对象不再代表data, but 格式说明 for PowerShell 的输出格式化系统- 它们没有其他目的。

因此,只需更换Format-Table with 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}

然而,这两个 cmdlet 的共同点是能够接受基于哈希表的计算属性 (@{ label = '...'; expression = { ... } }),就像你的问题一样。


As for 到底发生了什么在你的尝试中:

这是一个简化的示例,使用Format-Table:

PS> [pscustomobject] @{ freespace = 100; size = 1000 } |
      Format-Table @{label='SpaceLeft'; expression={$_.freespace / $_.size * 100}}

SpaceLeft
---------
       10

This looks很好——事实上这就是目的——制作一个好的display表示。

事实上,替代Select-Object for Format-Table结果相同display:

PS> [pscustomobject] @{ freespace = 100; size = 1000 } |
      Select-Object @{ label='SpaceLeft'; expression={$_.freespace / $_.size * 100} }

SpaceLeft
---------
       10

原因是当命令输出到达display, 电源外壳隐秘地,在幕后打电话给合适的 Format-* cmdlet,在本例中是Format-Table。 换句话说,上面的命令相当于下面的命令:

PS> [pscustomobject] @{ freespace = 100; size = 1000 } |
      Select-Object @{label='SpaceLeft'; expression={$_.freespace / $_.size * 100}} |
        Format-Table 

SpaceLeft
---------
       10

For the 背后的逻辑which Format-*选择了 cmdletwhen, see 这个答案.

然而,而不是(隐式)应用Format-Table,您可以选择不同的格式化 cmdlet,例如Format-List对于列表样式显示,在其自己的行上显示每个属性:

PS> [pscustomobject] @{ freespace = 100; size = 1000 } |
      Select-Object @{label='SpaceLeft'; expression={$_.freespace / $_.size * 100}} |
        Format-List

SpaceLeft : 10

然而,当谈到进一步处理, Select-Object and Format-Table are not只创造平等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调用即可操作。

Using 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 are not在输出中同样存在。

    • 这就是为什么你的Where-Object通话未按预期进行:$_.SpaceLeft引用了一个不存在的属性,因此表达式的计算结果为$null, and $null -lt 10 is always $true.

无论他们的输入如何,Format-*cmdlet 输出实例Microsoft.PowerShell.Commands.Internal.Format.*代表的类型格式说明.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在表结构上添加一个where-对象? 的相关文章

随机推荐