about_PSItem
Kort beskrivning
Den automatiska variabeln som innehåller det aktuella objektet i pipelineobjektet.
Lång beskrivning
PowerShell innehåller variabeln $PSItem
och dess alias, $_
, som automatiska variabler i skriptblock som bearbetar det aktuella objektet, till exempel i pipelinen. Den här artikeln används $PSItem
i exemplen, men $PSItem
kan ersättas med $_
i varje exempel.
Du kan använda den här variabeln i kommandon som utför en åtgärd på varje objekt i en pipeline.
Det finns några vanliga användningsfall för $PSItem
:
- i scriptblock för parametern Process för cmdleten
ForEach-Object
- i scriptblock för parametern FilterScript för cmdleten
Where-Object
- i de inbyggda metoderna ForEach och Where
- med parametrar för skriptblockering med fördröjningsbindning
- i en
switch
instruktions villkorsvärden och associerade skriptblock - i blocket för
process
en funktion - i en
filter
definition - i skriptblocket för attributet ValidateScript
- i ersättningen operand scriptblock för operatorn
-replace
Resten av den här artikeln innehåller exempel på användning $PSItem
för dessa användningsfall.
ForEach-Object Process
Cmdleten ForEach-Object är utformad för att fungera på objekt i pipelinen och köra processparameterns scriptblock en gång för varje objekt i pipelinen.
Du kan använda $PSItem
i processparameterns scriptblock men inte i skriptblocken Begin eller End . Om du refererar till $PSItem
i skriptblocken för parametern Begin eller End beror $null
värdet på att dessa skriptblock inte fungerar på varje objekt i pipelinen.
$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
Cmdleten Where-Object är utformad för att filtrera objekt i pipelinen.
Du kan använda $PSItem
i scriptblock för FilterScript-parametern , som körs en gång för varje indataobjekt i pipelinen.
1, 2, 3 | Where-Object -FilterScript { ($PSItem % 2) -eq 0 }
2
I det här exemplet kontrollerar FilterScript om det aktuella objektet är jämnt, filtrerar bort några udda värden och returnerar endast 2
från den ursprungliga listan.
ForEach- och Where-metoder
Både ForEach och Where intrinsic methods for arrays tar en scriptblock som indataparameter. Du kan använda $PSItem
i dessa skriptblock för att komma åt det aktuella objektet.
@('a', 'b', 'c').ForEach({ $PSItem.ToUpper() }).Where({ $PSItem -ceq 'B' })
B
I det här exemplet är skriptblocket för ForEach-metoden versaler för det aktuella objektet. Sedan returnerar scriptblock för metoden Where endast B
.
Parametrar för skriptblockering med fördröjningsbindning
Med skriptblock med fördröjningsbindning kan du använda $PSItem
för att definiera parametrar för en pipelined cmdlet innan du kör den.
dir config.log | Rename-Item -NewName { "old_$($_.Name)" }
Växla instruktionsskriptblock
I switch-instruktioner kan du använda $PSItem
i både åtgärdsskriptblockeringar och skriptblock för instruktionsvillkor.
$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
I det här exemplet kontrollerar instruktionsvillkoret scriptblock om det aktuella objektet är jämnt. Om den är jämn matar den associerade åtgärden scriptblock ut ett meddelande som anger att det aktuella objektet är jämnt.
Åtgärdsskriptblocket för villkoret default
matar ut ett meddelande som anger att det aktuella objektet är udda.
Funktionsprocessblock
När du definierar en funktion kan du använda $PSItem
i blockdefinitionen process
begin
men inte i eller end
blockera definitioner. Om du refererar till $PSItem
i begin
eller-blocken end
beror $null
värdet på att dessa block inte fungerar på varje objekt i pipelinen.
När du använder $PSItem
i blockdefinitionen process
är värdet det aktuella objektet om funktionen anropas i pipelinen och annars $null
.
function Add-One {
process { $PSItem + 1 }
}
1, 2, 3 | Add-One
2
3
4
Dricks
Även om du kan använda $PSItem
i avancerade funktioner finns det ingen anledning att göra det. Om du tänker ta emot indata från pipelinen är det bäst att definiera parametrar med ett av argumenten ValueFromPipeline*
för parameterattributet.
Om du använder parameterattributet och cmdlet-bindningen för avancerade funktioner blir implementeringen mer explicit och förutsägbar än att bearbeta det aktuella objektet för att hämta de värden som krävs.
En bra användning av $PSItem
i avancerade funktioner är att inspektera själva det aktuella objektet för felsökning eller loggning när funktionen har flera parametrar som tar indata från pipelinen.
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
}
}
Den här exempelfunktionen matar ut en matris med JSON-objekt med ett meddelande och en tidsstämpel. När den anropas i en pipeline använder den egenskapen Meddelande för det aktuella objektet för varje post. Den skriver också JSON-representationen av själva det aktuella objektet till den utförliga strömmen, så att du kan se de faktiska indata jämfört med utdataloggarna.
$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)\/"
}
]
Filterdefinitioner
Du kan använda $PSItem
i instruktionslistan för ett filters definition.
När du använder $PSItem
i en filter
definition är värdet det aktuella objektet om filtret anropas i pipelinen och annars $null
.
filter Test-IsEven { ($PSItem % 2) -eq 0 }
1, 2, 3 | Test-IsEven
False
True
False
I det här exemplet Test-IsEven
matas $true
filtret ut om det aktuella objektet är ett jämnt tal och $false
om det inte är det.
Scriptblock för ValidateScript-attribut
Du kan använda $PSItem
i skriptblocket för ett ValidateScript-attribut .
När det används med ValidateScript $PSItem
är värdet för det aktuella objektet som verifieras. När variabel- eller parametervärdet är en matris anropas scriptblock en gång för varje objekt i matrisen med $PSItem
som aktuellt objekt.
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.
I det här exemplet körs scriptblock för attributet ValidateScript en gång för varje värde som skickas till parametern Number , vilket returnerar ett fel om något värde inte ens är det.
Funktionen Add-EvenNumber
lägger till giltiga indatanummer och returnerar summan.
-replace-operatorns ersättningsskriptblockering
Från och med PowerShell 6 kan du använda $PSItem
när du anropar ersättningsoperatorn och definierar en ersättningsskriptblockering. När du gör det är värdet $PSItem
för värdet för den aktuella matchningen.
$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
I det här exemplet ersätter substitution scriptblock den ursprungliga datumsträngen med standardformatet för den aktuella kulturen genom att ange värdet till datetime.