about_PSItem
簡短描述
包含管線物件中目前對象的自動變數。
詳細描述
PowerShell 包含 $PSItem
變數及其別名, $_
做為 腳本區塊中處理目前對象的自動變數 ,例如在管線中。 本文 $PSItem
會在範例中使用 ,但 $PSItem
可以在每個範例中取代為 $_
。
您可以在命令中使用這個變數,在管線中的每個物件上執行動作。
有一些常見的使用案例 $PSItem
:
- 在 Cmdlet 之 Process 參數的
ForEach-Object
scriptblock 中 - Cmdlet 之 FilterScript 參數
Where-Object
的 scriptblock 中 - In the intrinsic methods ForEach and Where
- 具有延遲系結腳本區塊參數
switch
在語句的條件值和相關聯的 scriptblock 中- 函式區塊
process
中的 filter
定義中的- 在 ValidateScript 屬性的 scriptblock 中
本文的其餘部分包含使用這些使用案例的 $PSItem
範例。
ForEach-Object Process
ForEach-Object Cmdlet 的設計目的是在管線中的物件上操作,針對管線中的每個物件執行 Process 參數的 scriptblock 一次。
您可以在 Process 參數的 scriptblock 中使用$PSItem
,但無法在 Begin 或 End 參數 scriptblocks 中使用。 如果您在 Begin 或 End 參數 scriptblocks 中參考 ,則值是因為$null
這些文稿區塊不會在管線中的每個物件上運作。$PSItem
$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
傳回 。
延遲系結腳本區塊參數
延遲系結腳本區塊 可讓您在執行之前,先 $PSItem
定義管線 Cmdlet 的參數。
dir config.log | Rename-Item -NewName { "old_$($_.Name)" }
Switch 語句 scriptblocks
在 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
在此範例中,語句條件腳本區塊會檢查目前的物件是否偶數。 如果是偶數,相關聯的動作腳本區塊會輸出訊息,指出目前的物件為偶數。
條件的 default
動作腳本區塊會輸出訊息,指出目前物件為奇數。
函式進程區塊
當您定義函式時,可以在$PSItem
區塊定義中使用process
,但無法在 或 end
區塊定義中使用begin
。 如果您在或 end
區塊中begin
參考 $PSItem
,則值是因為$null
這些區塊不會在管線中的每個物件上運作。
當您 $PSItem
在區塊定義中使用 process
時,如果管線中呼叫函式,則值為值是目前的物件,否則 $null
為 。
function Add-One {
process { $PSItem + 1 }
}
1, 2, 3 | Add-One
2
3
4
提示
雖然您可以在$PSItem
進階函式中使用,但幾乎沒有理由這麼做。 如果您想要從管線接收輸入,最好是使用Parameter屬性的ValueFromPipeline*
其中一個自變數來定義參數。
針對進階函式使用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 : 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.
At line:1 char:24
+ Add-EvenNumber -Number 1, 2
+ ~~~~
+ CategoryInfo : InvalidData: (:) [Add-EvenNumber],
ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,
Add-EvenNumber
在此範例中,ValidateScript 屬性的 scriptblock 會針對傳遞給 Number 參數的每個值執行一次,如果沒有任何值甚至沒有傳回錯誤, 就會傳回錯誤。
函 Add-EvenNumber
式會新增有效的輸入編號,並傳回總計。