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 processbegin 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.

Se även