精通PowerShell Where-Object:全面指南

當您在一個對象集合中處理 PowerShell 屬性值時,有時您需要一種方法來過濾掉所有您不需要的東西。知道如何使用 PowerShell 的 Where-Object 命令是您 PowerShell 工具箱中重要的技能。

Where-Object 命令是一種方便的過濾對象的方法。在本教程中,您將學習不同的構造 Where-Object 命令的方法,以及它的可用參數、語法,以及如何像專業人士一樣使用多個條件!

先決條件

本文只有一個先決條件。您應該對 PowerShell 命令和語法有一些基本的熟悉。

本文中的所有示例都基於 當前穩定版本的 PowerShell(撰寫時為 7.1.0)。但只要您使用的是 Windows PowerShell 4.0 或更高版本,這些命令將運作相同。

理解 PowerShell Where-Object 的工作原理

PowerShell 的 Where-Object 命令的唯一目標是過濾命令返回的輸出,只返回您想要看到的信息。

簡而言之,Where-Object 命令是一個過濾器;就這樣。它允許您構造一個返回 True 或 False 的條件。根據該條件的結果,該命令要麼返回輸出,要麼不返回。

您可以用两种方式之一来创建这个条件;“旧”方式使用脚本块,以及使用参数或比较语句的“新”方式。

使用脚本块创建筛选条件

脚本块是PowerShell中的一个关键组件。脚本块在语言的许多地方都有使用。脚本块是一个匿名函数,它可以将代码分隔开并在不同的地方执行。您可以通过脚本块构建Where-Object的筛选器。

要将脚本块用作筛选器,您需要使用FilterScript参数。该参数允许您创建和传递一个脚本块给FilterScript参数,然后执行该脚本块。

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

例如,假设您需要找到当前启动类型为Automatic的所有Windows服务。您可以首先使用Get-Service获取所有当前服务。然后,Get-Service将返回许多不同的服务对象以及各种属性。

使用 PowerShell 管線,您可以將這些物件傳送到 Where-Object cmdlet,並使用 FilterScript 參數。由於 FilterScript 參數接受一個 scriptblock,您可以建立一個條件來檢查每個物件的 StartType 屬性是否等於 Automatic,如下所示。

{$_.StartType -EQ 'Automatic'}

一旦您有了篩選的 scriptblock,您就可以將該 scriptblock 提供給 FilterScript 參數。Where-Object 將會對管線中的每個物件執行該 scriptblock,並評估每個 StartType 屬性。如果該屬性等於 Automatic,則 Where-Object 會通過該物件。如果不是,該物件將被丟棄。

您可以在下面看到一個簡單的例子。

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

許多人在使用 Where-Object cmdlet 時使用位置參數,並且不包含 FilterScript 參數名稱。相反,他們只提供 scriptblock,例如 Where-Object {$_.StartType -eq 'Automatic'}

雖然這種構造對於這個特定的情境可以工作,但 scriptblock 的概念使用大括號或者 管線變數 $_ 使得代碼不易閱讀,對於較不熟悉 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[運算符] 開頭的包含運算符

相關連結:通過示例了解 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'

也許您想更進一步,查找所有狀態不是 RunningStartType 是一個名為 Manual 的字串(或可能是一個數組)的服務。使用以下腳本塊,命令使用 FilterScript 參數傳遞一個腳本塊來評估這兩個條件。

相關連結:回到基礎:理解 PowerShell 對象

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

當您執行上述命令時,您只會看到已停止且具有手動StartType的服務。

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 cmdlet,這不是問題。

使用腳本區塊,您可以使用 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 命令來過濾各種東西,還可以做什麼呢?嘗試使用多個條件和運算符對集合進行更複雜的過濾任務,以過濾出屬性值並按照您的喜好格式化輸出。

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