about_PSItem
簡短描述
包含管線物件中目前對象的自動變數。
完整描述
PowerShell 包含 $PSItem
變數及其別名, $_
作為腳本區塊中處理目前對象的 自動變數 ,例如在管線中。 本文會在 $PSItem
範例中使用,但 $PSItem
可以在每個範例中取代 $_
為 。
您可以在命令中使用這個變數,在管線中的每個物件上執行動作。
有一些常見的使用案例 $PSItem
:
- 在 Cmdlet 之 Process 參數的
ForEach-Object
scriptblock 中 - 在 Cmdlet 之 FilterScript 參數的
Where-Object
scriptblock 中 - 在內部方法 ForEach 和 Where 中
- 具有延遲系結 scriptblock 參數
switch
在語句的條件值和相關聯的 scriptblock 中process
在函式的 區塊中filter
定義中的- 在 ValidateScript 屬性的 scriptblock 中
- 在運算子的
-replace
替代操作數腳本區塊中
本文的其餘部分包含使用這些 $PSItem
使用案例的範例。
ForEach-Object 程式
ForEach-Object Cmdlet 的設計目的是要對管線中的物件操作,針對管線中的每個物件執行 Process 參數的 scriptblock 一次。
您可以在 Process 參數的 scriptblock 中使用,但不能在 $PSItem
Begin 或 End 參數 scriptblocks 中使用。 如果您在 Begin 或 End 參數 scriptblocks 中參考$PSItem
,則值是因為$null
這些腳本區塊不會在管線中的每個物件上運作。
$parameters = @{
Begin = { Write-Host "PSItem in Begin is: $PSItem" }
Process = {
Write-Host "PSItem in Process is: $PSItem"
$PSItem + 1
}
End = { Write-Host "PSItem in End is: $PSItem" }
}
$result = 1, 2, 3 | ForEach-Object @parameters
Write-Host "Result is: $result"
PSItem in Begin is:
PSItem in Process is: 1
PSItem in Process is: 2
PSItem in Process is: 3
PSItem in End is:
Result is: 2 3 4
Where-Object FilterScript
Where-Object Cmdlet 的設計目的是要篩選管線中的物件。
您可以在 $PSItem
FilterScript 參數的 scriptblock 中使用,該參數會針對管線中的每個輸入物件執行一次。
1, 2, 3 | Where-Object -FilterScript { ($PSItem % 2) -eq 0 }
2
在此範例中, FilterScript 會檢查目前的物件是否為偶數、篩選掉任何奇數值,並且只 2
從原始清單傳回。
ForEach 和 Where 方法
陣列的 ForEach 和 Where 內建方法都會採用 scriptblock 作為輸入參數。 您可以使用 $PSItem
這些文稿區塊中的 來存取目前的物件。
@('a', 'b', 'c').ForEach({ $PSItem.ToUpper() }).Where({ $PSItem -ceq 'B' })
B
在此範例中, ForEach 方法的 scriptblock 會大寫目前的 物件。 然後 Where 方法的 scriptblock 只會 B
傳回 。
延遲系結 scriptblock 參數
延遲系結腳本區塊 可讓您先定義 $PSItem
管線 Cmdlet 的參數,再執行它。
dir config.log | Rename-Item -NewName { "old_$($_.Name)" }
Switch 語句腳本區塊
在 switch 語句中,您可以在動作腳本區塊和語句條件腳本區塊中使用 $PSItem
。
$numbers = 1, 2, 3
switch ($numbers) {
{ ($PSItem % 2) -eq 0 } { "$PSItem is even" }
default { "$PSItem is odd" }
}
1 is odd
2 is even
3 is odd
在此範例中,語句條件 scriptblock 會檢查目前的物件是否偶數。 如果甚至如此,相關聯的動作腳本區塊會輸出訊息,指出目前的物件甚至為偶數。
條件的 default
動作腳本區塊會輸出訊息,指出目前的對像是奇數的。
函式進程區塊
當您定義函式時,可以在區塊定義中使用process
,但不能begin
用於 $PSItem
或 end
區塊定義。 如果您在或 end
區塊中begin
參考 $PSItem
,則值是因為$null
這些區塊不會在管線中的每個物件上運作。
當您 $PSItem
在區塊定義中使用 process
時,如果函式在管線中呼叫 ,則值為值是目前對象,否則 $null
為 。
function Add-One {
process { $PSItem + 1 }
}
1, 2, 3 | Add-One
2
3
4
針對進階函式使用 Parameter 屬性和 Cmdlet 系結,可讓實作比處理目前物件更明確且可預測,以取得所需的值。
在進階函式中,有一個良好的用法 $PSItem
是檢查目前的物件本身,以在函式有多個從管線取得輸入的參數時進行偵錯或記錄。
function Write-JsonLog {
[CmdletBinding()]
param(
[parameter(ValueFromPipelineByPropertyName)]
[string]$Message
)
begin {
$entries = @()
}
process {
$entries += [pscustomobject]@{
Message = $Message
TimeStamp = [datetime]::Now
}
if ($PSItem) {
$props = $PSItem | ConvertTo-Json
$number = $entries.Length
Write-Verbose "Input object $number is:`n$props"
}
}
end {
ConvertTo-Json -InputObject $entries
}
}
此範例函式會輸出具有訊息和時間戳的 JSON 物件數位。 在管線中呼叫時,它會針對每個專案使用目前物件的 Message 屬性。 它也會將目前物件的 JSON 表示法寫入至詳細資訊數據流,因此您可以查看與輸出記錄相較的實際輸入。
$Items = @(
[pscustomobject]@{
Name = 'First Item'
Message = 'A simple note'
}
[pscustomobject]@{
Name = 'Item with extra properties'
Message = 'Missing message, has info instead'
Info = 'Some metadata'
Source = 'Where this came from'
}
[pscustomobject]@{
Name = 'Last Item'
Message = 'This also gets logged'
}
)
$Items | Write-JsonLog -Verbose
VERBOSE: Input object 1 is:
{
"Name": "First Item",
"Message": "A simple note"
}
VERBOSE: Input object 2 is:
{
"Name": "Item with extra properties",
"Message": "Missing message, has info instead",
"Info": "Some metadata",
"Source": "Where this came from"
}
VERBOSE: Input object 3 is:
{
"Name": "Last Item",
"Message": "This also gets logged"
}
[
{
"Message": "A simple note",
"TimeStamp": "\/Date(1670344068257)\/"
},
{
"Message": "Missing message, has info instead",
"TimeStamp": "\/Date(1670344068259)\/"
},
{
"Message": "This also gets logged",
"TimeStamp": "\/Date(1670344068261)\/"
}
]
篩選定義
您可以在篩選定義的語句清單中使用 $PSItem
。
當您在 $PSItem
定義中使用 filter
時,如果管線中呼叫篩選條件,則此值為目前對象,否則 $null
為 。
filter Test-IsEven { ($PSItem % 2) -eq 0 }
1, 2, 3 | Test-IsEven
False
True
False
在此範例中Test-IsEven
,如果目前的對像是偶數,而且$false
不是,則篩選會輸出$true
。
ValidateScript 屬性腳本區塊
您可以在 ValidateScript 屬性的 scriptblock 中使用$PSItem
。
搭配 ValidateScript 使用時, $PSItem
是正在驗證之目前物件的值。 當變數或參數值是陣列時,會針對陣列中的每個物件呼叫 scriptblock 一次,並將 $PSItem
作為目前物件。
function Add-EvenNumber {
param(
[ValidateScript({ 0 -eq ($PSItem % 2) })]
[int[]]$Number
)
begin {
[int]$total = 0
}
process {
foreach ($n in $Number) {
$total += $n
}
}
end {
$total
}
}
Add-EvenNumber -Number 2, 4, 6
Add-EvenNumber -Number 1, 2
12
Add-EvenNumber:
Line |
24 | Add-EvenNumber -Number 1, 2
| ~~~~
| Cannot validate argument on parameter 'Number'. The
" 0 -eq ($PSItem % 2) " validation script for the argument
with value "1" did not return a result of True. Determine
why the validation script failed, and then try the command
again.
在此範例中, ValidateScript 屬性的 scriptblock 會針對傳遞至 Number 參數的每個值執行一次,如果沒有任何值甚至不會傳回錯誤。
函式 Add-EvenNumber
會新增有效的輸入數位,並傳回總計。
-replace 運算符的替代 scriptblock
從 PowerShell 6 開始,您可以在呼叫 replace 運算子並定義替代腳本區塊時使用$PSItem
。 當您這樣做時,的值 $PSItem
是目前相符專案的值。
$datePattern = '\d{4}-\d{2}-\d{2}'
'Today is 1999-12-31' -replace $datePattern, { [datetime]$PSItem.Value }
Today is 12/31/1999 00:00:00
在此範例中,替代 scriptblock 會藉由將值轉換成 datetime,以目前文化特性的預設格式取代原始日期字串。