HOWTO · PowerShell

如何在 PowerShell 中使用 Where-Object 命令

了解如何使用 Where-Object 篩選管線物件,涵蓋腳本區塊、屬性條件、別名與組合述詞。

本頁內容

使用 Where-Object,只保留 PowerShell 管線中符合條件的物件。條件可以透過腳本區塊檢查目前的物件,也可以使用 cmdlet 簡化的屬性語法進行常見比較。以下範例使用少量固定資料,方便你調整述詞,無須依賴電腦上的檔案或執行中的處理程序。

Where-Object Cmdlet 在 PowerShell 中的用途

PowerShell 命令通常會透過管線傳遞物件。Where-Object 會對每個傳入物件評估一次條件,只有條件成立時才輸出該物件。在腳本區塊中,$_ 代表目前正在評估的物件。當集合中的項目多於下一個命令所需時,這個 cmdlet 就很實用。

例如,以下管線會保留 Status 為 Ready 的兩筆記錄,並輸出其名稱。這是可依照自己的物件屬性調整的基本模式:

本節中的程式碼以及顯示的標籤或輸出仍為英文。

$tasks = @(
    [pscustomobject]@{ Name = 'Build'; Status = 'Ready' }
    [pscustomobject]@{ Name = 'Test'; Status = 'Waiting' }
    [pscustomobject]@{ Name = 'Package'; Status = 'Ready' }
)
$tasks | Where-Object { $_.Status -eq 'Ready' } | ForEach-Object { $_.Name }

在 PowerShell 中使用腳本區塊建立篩選條件

腳本區塊是以大括號括住的程式碼。搭配 Where-Object 使用時,它會作為述詞:系統會對每個管線物件評估其中的運算式,結果為真的物件就會通過篩選。你可以使用 -FilterScript 指定腳本區塊參數名稱,也可以直接以位置參數傳入:

本節中的程式碼以及顯示的標籤或輸出仍為英文。

$services = @(
    [pscustomobject]@{ Name = 'Archive'; StartType = 'Automatic' }
    [pscustomobject]@{ Name = 'Indexer'; StartType = 'Manual' }
)
$services | Where-Object -FilterScript { $_.StartType -eq 'Automatic' }

位置參數形式使用相同條件,語法較為精簡:$services | Where-Object { $_.StartType -eq 'Automatic' }。兩種形式都會在物件進入管線時逐一評估。若明確指出參數用途能讓程式碼更易讀,就使用具名形式;若邏輯涉及多個屬性或運算子,腳本區塊仍然很實用。

使用 Where-Object 篩選 PowerShell 物件

只要管線物件具有要測試的屬性,就能使用屬性述詞。例如,以下示範如何依副檔名篩選一組固定的檔案資料:

本節中的程式碼以及顯示的標籤或輸出仍為英文。

$files = @(
    [pscustomobject]@{ Name = 'notes.csv'; Extension = '.csv' }
    [pscustomobject]@{ Name = 'readme.txt'; Extension = '.txt' }
    [pscustomobject]@{ Name = 'sales.csv'; Extension = '.csv' }
)
$files | Where-Object { $_.Extension -eq '.csv' }

若要處理實際目錄中的內容,Get-ChildItem 會產生檔案系統物件。將所需的目錄清單指派給 $items 後,可以使用類似的述詞:$items | Where-Object { $_.Extension -eq '.csv' }。符合條件的項目取決於該目錄的實際內容。Where 是 Where-Object 的別名,因此也可以在相同的腳本區塊形式中使用 Where。

在 PowerShell 中使用參數建立篩選條件

對於常見比較,可以使用簡化語法,直接在 Where-Object 後指定屬性、比較參數和值。例如,$tasks | Where-Object -Property Status -EQ 'Ready' 會依 Status 屬性篩選。此處的 -Property 和 -EQ 都是 Where-Object 的參數;參數名稱不區分大小寫,因此在這種語法中,-eq 和 -EQ 指的是同一個比較參數。在腳本區塊中,-eq 則是比較運算子,例如 $_.Status -eq 'Ready'。

若要簡潔地比較單一屬性,這種形式很合適。如果條件需要更細緻的控制,例如比較兩個屬性或組合多個述詞,請使用腳本區塊。這兩種寫法都會篩選傳入的物件,不會修改物件本身。

使用多個條件陳述式

如果所有條件都必須成立,可在腳本區塊中用 -and 組合條件;若任一條件成立即可,則使用 -or。括號可將比較式分組,讓邏輯更容易閱讀;括號並非特殊子運算式的必要條件。

本節中的程式碼以及顯示的標籤或輸出仍為英文。

$tasks = @(
    [pscustomobject]@{ Name = 'Build'; Status = 'Ready'; Priority = 1 }
    [pscustomobject]@{ Name = 'Test'; Status = 'Waiting'; Priority = 1 }
    [pscustomobject]@{ Name = 'Package'; Status = 'Ready'; Priority = 3 }
)
$tasks | Where-Object { ($_.Status -eq 'Ready') -and ($_.Priority -le 2) }
$tasks | Where-Object { ($_.Name -eq 'Test') -or ($_.Priority -ge 3) }

第一個條件只保留狀態為就緒且優先順序為 2 或更低的記錄。第二個條件則保留名稱為 Test 或優先順序為 3 或更高的記錄。請依照篩選工作需要所有條件都成立,還是任一條件成立,來選擇 -and 或 -or。