本文介绍了在表结构上添加一个 where 对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

用label"重命名标题,我想过滤最后一个SpaceLeft".但是它不能正常工作.例如:

Renaming the headers with 'label' and I'd like to filter on that last one 'SpaceLeft'. It doesn't work correctly though. For example:

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"中的值大于 WHERE 语句中指定的 10,但它返回了结果.这是为什么??

This should come back with nothing as the value in 'SpaceLeft' is greater than 10 being specified in the WHERE statement, yet it comes back with results. Why is this??

推荐答案

Lee Dailey 提供了关键指针在评论中:

Lee Dailey has provided the crucial pointer in a comment:

  • To transform data for further programmatic processing, use Select-Object or other data-transformation methods, such as via ForEach-Object.

仅使用 Format-* cmdlet 来格式化数据显示,作为它们的名字暗示.

Only ever use the Format-* cmdlets to format data for display, as their name suggests.

  • PowerShell 的重大进化飞跃是通过管道发送对象而不是文本,而 Format-* cmdlet,例如 格式表 也发出对象,这些对象不再代表数据,而是 - 它们没有其他用途.
  • PowerShell's great evolutionary leap was to send objects rather than text through the pipeline, and while Format-* cmdlets such as Format-Table emit objects as well, these objects no longer represent data, but formatting instructions for PowerShell's output-formatting system - they serve no other purpose.

因此,只需将 Format-Table 替换为 Select-Object 即可解决您的问题:

Therefore, simply replacing Format-Table with Select-Object solves your problem:

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 = { ... } }),就像你的问题一样.

What the two cmdlets do have in common, however, is the ability to accept hashtable-based calculated properties (@{ label = '...'; expression = { ... } }), as in your question.

至于实际发生了什么:

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

Here's a simplified example, using Format-Table:

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

SpaceLeft
---------
       10

看起来很好 - 事实上这就是目的 - 产生一个漂亮的显示表示.

This looks just fine - and indeed that's the purpose - producing a nice display representation.

事实上,用Select-Object代替Format-Table会得到相同的显示:

In fact, substituting Select-Object for Format-Table results in the same display:

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

SpaceLeft
---------
       10

原因是,当命令输出到显示时,PowerShell 隐式地,在幕后调用适当的Format-* cmdlet,在本例中为 Format-Table.换句话说,上面的命令等价于下面的命令:

The reason is that when command output goes to the display, PowerShell implicitly, behind the scenes calls an appropriate Format-* cmdlet, which in this case is Format-Table.In other words, the command above is equivalent to the following command:

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

SpaceLeft
---------
       10

有关选择哪个 Format-* cmdlet 的逻辑何时,请参阅这个答案.

For the logic behind which Format-* cmdlet is chosen when, see this answer.

但是,您可以选择不同的格式化 cmdlet,例如用于列表样式显示的 Format-List,而不是(隐式)应用的 Format-Table在单独的行中显示每个属性:

However, instead of the (implicitly) applied Format-Table, you could have chosen a different formatting cmdlet, such as Format-List for list-style display that shows each property on its own line:

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

SpaceLeft : 10


然而,当涉及到进一步处理时,Select-ObjectFormat-Table没有创建相等 - 只有 Select-Object 是合适的:


However, when it comes to further processing, Select-Object and Format-Table are not created equal - only Select-Object is suitable:

让我们看看输出对象拥有哪些属性,使用 Get-Member -Type Properties,首先使用 Select-Object:

Let's look at what properties the output object(s) possess, using Get-Member -Type Properties, first with 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 调用可以操作的内容.

As expected, the output has one property, named SpaceLeft, and that's what your Where-Object call can operate on.

使用 Format-Table 而不是 Select-Object 讲述了一个不同的故事:

Using Format-Table instead of Select-Object tells a different story:

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

这些部分模糊命名的属性具体代表什么并不重要 - 重要的是:

It doesn't really matter what these in part obscurely named properties specifically represent - all that matters is:

  • 它们的唯一目的是被 PowerShell 的输出格式系统解释.

  • Their sole purpose is to be interpreted by PowerShell's output-formatting system.

传递给 Format-Table 的选定/计算属性出现在输出中.

The selected / calculated properties passed to Format-Table are not present as such in the output.

  • 这就是您的 Where-Object 调用没有按预期工作的原因:$_.SpaceLeft 引用了一个不存在的属性,因此表达式的计算结果为 $null$null -lt 10 总是 $true.
  • That's why your Where-Object call didn't work as intended: $_.SpaceLeft referenced a non-existing property, so the expression evaluates to $null, and $null -lt 10 is always $true.

不管他们的输入是什么,Format-* cmdlet 都会输出 Microsoft.PowerShell.Commands.Internal.Format.* 表示格式说明的类型.

Irrespective of their input, Format-* cmdlets output instances of Microsoft.PowerShell.Commands.Internal.Format.* types that represent formatting instructions.

这篇关于在表结构上添加一个 where 对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-31 12:06