当您处理对象集合中的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,如下所示。
有了筛选脚本块后,您可以将该脚本块提供给 FilterScript
参数。Where-Object
将为管道上传递的每个对象执行该脚本块,并评估每个 StartType
属性。如果属性等于 Automatic,Where-Object
将传递该对象。否则,将丢弃该对象。
您可以在下面看到此方法的简单示例。

许多人在与
Where-Object
命令一起使用定位参数,并省略FilterScript
参数名称。相反,他们只提供脚本块,如Where-Object {$_.StartType -eq 'Automatic'}
。
虽然这种构造对于这种特定情景有效,但脚本块中的花括号或甚至 管道变量 $_
会使代码变得不够可读,对于经验较少的 PowerShell 用户而言更加困难。这种可读性问题是导致 PowerShell 团队引入参数或比较语句的原因。
比较语句
在 Windows PowerShell 3.0 中引入了比较语句,它们的构造方式更加自然。使用与上一个示例相同的场景,让我们使用比较语句构造来查找所有启动类型为“自动”的 Windows 服务:
请注意,上面的命令没有使用脚本块,而是将对象属性指定为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]
开头的包含运算符。
假设您想要检查BITS Windows 服务的状态。您可以通过向contains
参数(运算符)传递BITS的值来执行此操作,如下所示。
下面是您可以预期看到的内容:

始终记得进行左侧过滤!前面的示例等同于运行
Get-Service -ServiceName 'BITS'
。
也许您想要更加高级,并查找所有状态不是运行的服务和启动类型为一个称为Manual的字符串(或可能是一个数组)。使用下面的脚本块,该命令使用FilterScript
参数传递一个脚本块,该脚本块对这两个条件进行评估。
当您运行上述命令时,您将只会看到已停止且具有StartType为Manual的服务。

使用包含运算符进行过滤对包含许多属性值的集合效果很好。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]
开头的匹配运算符
几乎与包含运算符在形式上相同,您可以使用如下所示的匹配运算符。下面的示例是查找所有具有Windows在DisplayName属性值中的服务。

match
operator uses regular expressions to match on certain values.您还可以使用like
运算符来使用常见的匹配技术,例如使用通配符(*
)匹配任何字符,或者使用?
匹配单个字符。
现在结果已经被过滤,只显示那些服务名称以‘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-Process
和 Where-Object
PowerShell 命令很容易解决。
使用脚本块,您可以使用 and
运算符将两个条件组合在一起,该运算符将对它们进行评估。如果它们都返回 True,则 Where-Object
将返回通过管道传递的进程对象。如果至少一个条件返回 False,则 Where-Object
将删除该对象。
以下是您期望看到的内容:

使用 Where-Object
相等运算符进行过滤将有助于您构建系统报告或比较值。
下一步
现在你对如何使用 PowerShell 的 `Where-Object
` cmdlet 进行过滤有了更多了解,还能做什么呢?尝试一些更复杂的过滤任务,使用多个条件和运算符对集合进行过滤,筛选出属性值并按照你的喜好格式化输出。
Source:
https://adamtheautomator.com/powershell-where-object/