掌握PowerShell Where-Object:全面指南

当您处理对象集合中的PowerShell属性值时,有时您需要一种方法来过滤掉所有不需要的内容。知道如何使用PowerShell Where-Object cmdlet 是您 PowerShell 工具箱中重要的技能。

PowerShell Where-Object cmdlet 是一种方便的过滤对象的方式。在本教程中,您将学习构建Where-Object命令的不同方法,以及它的可用参数、语法,以及如何像专业人士一样使用多个条件!

先决条件

本文只有一个先决条件。您应该对PowerShell命令和语法有一些基本的了解。

本文中的所有示例都将基于PowerShell的当前稳定版本(写作时为7.1.0)。但只要您使用的是Windows PowerShell 4.0及更高版本,命令将起到相同的作用。

理解 PowerShell Where-Object 的工作原理

PowerShell Where-Object cmdlet 的唯一目标是过滤命令返回的输出,只返回您想要查看的信息。

简而言之,Where-Object cmdlet 就是一个过滤器;仅此而已。它允许您构建一个返回True或False的条件。根据该条件的结果,cmdlet 然后要么返回输出,要么不返回。

您可以用两种方式来创建该条件;使用“旧”的方法,即使用脚本块,或者使用参数或比较语句的“新”方法。

使用脚本块创建过滤条件

脚本块是PowerShell中的一个关键组件。脚本块在语言中的许多地方都有所应用。脚本块是一个匿名函数。它是一种将代码分隔和在各个地方执行的方法。您可以通过脚本块构建Where-Object的过滤器。

要将脚本块用作过滤器,您可以使用FilterScript参数。该参数允许您创建并传递一个脚本块到FilterScript参数,然后执行该脚本块。

如果脚本块返回的值不是布尔False或null变量,则被视为True。否则,被视为False。

例如,假设您需要查找当前启动类型为自动的所有Windows服务。您首先会使用Get-Service来收集所有当前服务。Get-Service然后返回许多具有不同属性的不同服务对象。

使用 PowerShell 管道,您可以将这些对象传递到 Where-Object 命令,然后使用 FilterScript 参数。由于 FilterScript 参数接受脚本块,您可以创建一个条件来检查每个对象的 StartType 属性是否等于 Automatic,如下所示。

{$_.StartType -EQ 'Automatic'}

有了筛选脚本块后,您可以将该脚本块提供给 FilterScript 参数。Where-Object 将为管道上传递的每个对象执行该脚本块,并评估每个 StartType 属性。如果属性等于 AutomaticWhere-Object 将传递该对象。否则,将丢弃该对象。

您可以在下面看到此方法的简单示例。

Get-Service | Where-Object -FilterScript {$_.StartType -EQ 'Automatic'}
Script Block construct

许多人在与 Where-Object 命令一起使用定位参数,并省略 FilterScript 参数名称。相反,他们只提供脚本块,如 Where-Object {$_.StartType -eq 'Automatic'}

虽然这种构造对于这种特定情景有效,但脚本块中的花括号或甚至 管道变量 $_ 会使代码变得不够可读,对于经验较少的 PowerShell 用户而言更加困难。这种可读性问题是导致 PowerShell 团队引入参数或比较语句的原因。

比较语句

在 Windows PowerShell 3.0 中引入了比较语句,它们的构造方式更加自然。使用与上一个示例相同的场景,让我们使用比较语句构造来查找所有启动类型为“自动”的 Windows 服务:

Get-Service | Where-Object -Property StartType -EQ 'Automatic'

请注意,上面的命令没有使用脚本块,而是将对象属性指定为Property参数的参数值。现在eq运算符也是一个参数,允许您将“自动”的值传递给它。

以这种方式使用参数现在完全消除了对脚本块的需求。

A scriptblock is a better choice when defining more complex filtering conditions. The Property parameter may not always be the best choice. If using a scriptblock, just remember to document your code using comments!

在接下来的部分中,您将了解可与Where-Object一起使用的可用比较运算符类型,以过滤所有内容。

过滤基础

使用参数,Where-Object使用常见比较运算符来过滤对象集合。让我们深入了解一些它们如何工作的示例。

包含运算符

在处理集合时,包含运算符非常有用。包含运算符允许您定义一个条件,即集合包含一个项目或不包含。

例如,假设您想要过滤集合中的特定属性值。您可以使用包含运算符。

在 PowerShell 中,您会发现几种不同的包含运算符:

  • -contains / -ccontains – 过滤包含属性值的集合。
  • -notcontains / -cnotcontains – 过滤不包含属性值的集合。
  • -in / -cin – 值在集合中,如果找到匹配项,则返回属性值。
  • -notin / -cnotin – 值不在集合中,如果没有属性值,则为null/$false

对于区分大小写,请使用以-c[operator]开头的包含运算符。

相关: 通过示例理解 PowerShell 比较运算符

假设您想要检查BITS Windows 服务的状态。您可以通过向contains参数(运算符)传递BITS的值来执行此操作,如下所示。

Get-Service | Where-Object -Property Name -Contains 'BITS'

下面是您可以预期看到的内容:

Where-Object equivalent to Get-Service -ServiceName ‘BITS’

始终记得进行左侧过滤!前面的示例等同于运行Get-Service -ServiceName 'BITS'

也许您想要更加高级,并查找所有状态不是运行的服务启动类型为一个称为Manual的字符串(或可能是一个数组)。使用下面的脚本块,该命令使用FilterScript参数传递一个脚本块,该脚本块对这两个条件进行评估。

相关: 回到基础:理解 PowerShell 对象

Get-Service |
	Where-Object {($_.Status -notcontains 'Running') -and ($_.StartType -in 'Manual')}

当您运行上述命令时,您将只会看到已停止且具有StartTypeManual的服务。

More advanced filtering of a collection of objects

使用包含运算符进行过滤对包含许多属性值的集合效果很好。Get-Service返回了大量属性,通过结合包含和逻辑运算符,可以更轻松地筛选这些属性。

匹配运算符

类似于您如何在Where-Object中使用包含运算符,您也可以使用匹配运算符。匹配运算符允许您匹配字符串中的子字符串。例如,'foofoo' -like '*foo*'返回True或'foofoo' -match 'foo'返回True。匹配运算符匹配字符串中的子字符串。

在PowerShell中,您可以在Where-Object中使用几种不同的匹配运算符。

  • -like / -clike – 字符串匹配通配符模式。
  • -notlike / -cnotlike – 字符串不匹配通配符模式。
  • -match / -cmatch – 字符串匹配正则表达式模式。
  • -notmatch / -cnotmatch – 字符串不匹配正则表达式模式

对于区分大小写,请使用以-c[operator]开头的匹配运算符

几乎与包含运算符在形式上相同,您可以使用如下所示的匹配运算符。下面的示例是查找所有具有WindowsDisplayName属性值中的服务。

Get-Service | Where-Object { $_.DisplayName -match 'Windows'}
The match operator uses regular expressions to match on certain values.

相关:使用PowerShell和正则表达式入门

您还可以使用like运算符来使用常见的匹配技术,例如使用通配符(*)匹配任何字符,或者使用?匹配单个字符。

Get-Service | Where-Object {($_.Name -like 'Win*')}

现在结果已经被过滤,只显示那些服务名称以‘Win’作为前三个字符的:

service names with ‘Win

使用通配符意味着您不必知道服务的完整名称。字符串的前几个字母就足够了。这些运算符还可以与逻辑运算符结合使用,以进一步增强过滤。

等式运算符

与使用包含和比较运算符的方法类似,您还可以在Where-Object中使用等式运算符。等式运算符在需要比较数值时非常有用。

例如,1 -eq 1将为True,而1 -gt 2将为False。PowerShell有许多不同的等式运算符,您可以将其用作Where-Object的参数或嵌套在条件脚本块中。

  • -eq / -ceq – 值等于指定的值。
  • -ne / -cne – 值不等于指定值。
  • -gt / -cgt – 值大于指定值。
  • -ge / -cge – 值大于或等于指定值。
  • -lt / -clt – 值小于指定值。
  • -le / -cle – 值小于或等于指定值。

例如,也许您想要查找所有占用 CPU 百分比在两到十之间的运行中进程。使用 Get-ProcessWhere-Object PowerShell 命令很容易解决。

使用脚本块,您可以使用 and 运算符将两个条件组合在一起,该运算符将对它们进行评估。如果它们都返回 True,则 Where-Object 将返回通过管道传递的进程对象。如果至少一个条件返回 False,则 Where-Object 将删除该对象。

Get-Process | Where-Object {($_.CPU -gt 2.0) -and ($_.CPU -lt 10)}

以下是您期望看到的内容:

Filtering with greater than and less than

使用 Where-Object 相等运算符进行过滤将有助于您构建系统报告或比较值。

下一步

现在你对如何使用 PowerShell 的 `Where-Object` cmdlet 进行过滤有了更多了解,还能做什么呢?尝试一些更复杂的过滤任务,使用多个条件和运算符对集合进行过滤,筛选出属性值并按照你的喜好格式化输出。

Source:
https://adamtheautomator.com/powershell-where-object/