about_PSItem

Kurze Beschreibung

Die automatische Variable, die das aktuelle Objekt im Pipelineobjekt enthält.

Lange Beschreibung

PowerShell enthält die $PSItem Variable und ihren Alias als $_automatische Variablen in Skriptblocks, die das aktuelle Objekt verarbeiten, z. B. in der Pipeline. In diesem Artikel werden die Beispiele verwendet $PSItem , können aber $PSItem in jedem Beispiel ersetzt $_ werden.

Sie können diese Variable in Befehlen verwenden, die eine Aktion für jedes Objekt in einer Pipeline ausführen.

Es gibt einige häufige Anwendungsfälle für $PSItem:

  • im Scriptblock für den Parameter "Process" des Cmdlets ForEach-Object
  • im Scriptblock für den FilterScript-Parameter des Cmdlets Where-Object
  • in den systeminternen Methoden ForEach und Where
  • mit Parametern für "delay-bind scriptblock"
  • in den bedingten Werten einer switch Anweisung und den zugehörigen Scriptblocks
  • process im Block einer Funktion
  • in einer filter Definition
  • im Scriptblock des ValidateScript-Attributs
  • im Ersetzungsoperndenskriptblock des -replace Operators

Der Rest dieses Artikels enthält Beispiele für die Verwendung $PSItem für diese Anwendungsfälle.

ForEach-Objektprozess

Das Cmdlet ForEach-Object ist für die Ausführung von Objekten in der Pipeline konzipiert, wobei der Scriptblock des Process-Parameters für jedes Objekt in der Pipeline einmal ausgeführt wird.

Sie können den Scriptblock des Process-Parameters verwenden$PSItem, aber nicht in den Skriptblocks des Begin- oder End-Parameters. Wenn Sie in den Skriptblocks für den Begin- oder End-Parameter verweisen$PSItem, liegt $null der Wert daran, dass diese Scriptblocks nicht für jedes Objekt in der Pipeline ausgeführt werden.

$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

Das Cmdlet Where-Object wurde entwickelt, um Objekte in der Pipeline zu filtern.

Sie können im Scriptblock des FilterScript-Parameters verwenden$PSItem, der für jedes Eingabeobjekt in der Pipeline einmal ausgeführt wird.

1, 2, 3 | Where-Object -FilterScript { ($PSItem % 2) -eq 0 }
2

In diesem Beispiel überprüft filterScript, ob das aktuelle Objekt gerade ist, filtert ungerade Werte und gibt nur 2 aus der ursprünglichen Liste zurück.

ForEach- und Where-Methoden

Sowohl die systeminternen Methoden ForEach als auch die systeminternen Methoden für Arrays verwenden einen Scriptblock als Eingabeparameter. Sie können die $PSItem in diesen Scriptblocks verwenden, um auf das aktuelle Objekt zuzugreifen.

@('a', 'b', 'c').ForEach({ $PSItem.ToUpper() }).Where({ $PSItem -ceq 'B' })
B

In diesem Beispiel wird mit dem Scriptblock der ForEach-Methode das aktuelle Objekt in Großbuchstaben geschrieben. Then the scriptblock of the Where method returns only B.

Delay-bind scriptblock-Parameter

Mit Skriptblocks mit Verzögerungsbindung können Sie $PSItem Parameter für ein weitergeleitetes Cmdlet definieren, bevor Sie es ausführen.

dir config.log | Rename-Item -NewName { "old_$($_.Name)" }

Switch-Anweisungsskriptblocks

In Switch-Anweisungen können Sie sowohl in Aktionsskriptblocks als auch in Anweisungsbedingungs-Skriptblocks verwenden $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

In diesem Beispiel überprüft der Skriptblock für die Anweisungsbedingung, ob das aktuelle Objekt gerade ist. Wenn dies sogar der Grund ist, gibt der zugeordnete Aktionsskriptblock eine Meldung aus, die angibt, dass das aktuelle Objekt gerade ist.

Der Aktionsskriptblock für die default Bedingung gibt eine Meldung aus, die angibt, dass das aktuelle Objekt ungerade ist.

Funktionsprozessblöcke

Wenn Sie eine Funktion definieren, können Sie in der process Blockdefinition, aber nicht in den begin Definitionen oder end Blockdefinitionen verwenden$PSItem. Wenn Sie in den endbegin Blöcken verweisen$PSItem, liegt $null der Wert daran, dass diese Blöcke nicht für jedes Objekt in der Pipeline ausgeführt werden.

Wenn Sie in der Blockdefinition verwenden$PSItem, ist der Wert der Wert das aktuelle Objekt, wenn die Funktion in der Pipeline aufgerufen wird und andernfalls $null.process

function Add-One {
    process { $PSItem + 1 }
}

1, 2, 3 | Add-One
2
3
4

Tipp

Während Sie in erweiterten Funktionen verwenden $PSItem können, gibt es wenig Grund, dies zu tun. Wenn Sie eingaben von der Pipeline empfangen möchten, ist es am besten, Parameter mit einem der ValueFromPipeline* Argumente für das Parameter-Attribut zu definieren.

Wenn Sie das Parameter-Attribut und die Cmdlet-Bindung für erweiterte Funktionen verwenden, wird die Implementierung expliziter und vorhersehbarer als die Verarbeitung des aktuellen Objekts, um die erforderlichen Werte abzurufen.

Eine gute Verwendung in $PSItem erweiterten Funktionen besteht darin, das aktuelle Objekt selbst für das Debuggen oder Protokollieren zu prüfen, wenn die Funktion über mehrere Parameter verfügt, die Eingaben aus der Pipeline übernehmen.

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
    }
}

Diese Beispielfunktion gibt ein Array von JSON-Objekten mit einer Nachricht und einem Zeitstempel aus. Wenn sie in einer Pipeline aufgerufen wird, wird die Message-Eigenschaft des aktuellen Objekts für jeden Eintrag verwendet. Außerdem wird die JSON-Darstellung des aktuellen Objekts selbst in den ausführlichen Datenstrom geschrieben, sodass Sie die tatsächliche Eingabe im Vergleich zu den Ausgabeprotokollen sehen können.

$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)\/"
    }
]

Filterdefinitionen

Sie können in der Anweisungsliste der Definition eines Filters verwenden$PSItem.

Wenn Sie in einer Definition verwenden$PSItem, ist der Wert das aktuelle Objekt, wenn der Filter in der Pipeline aufgerufen wird und andernfalls $null.filter

filter Test-IsEven { ($PSItem % 2) -eq 0 }

1, 2, 3 | Test-IsEven
False
True
False

In diesem Beispiel gibt der Test-IsEven Filter aus $true , wenn das aktuelle Objekt eine gerade Zahl ist und $false wenn dies nicht der Fall ist.

Der Scriptblock des ValidateScript-Attributs

Sie können im Scriptblock eines ValidateScript-Attributs verwenden$PSItem. Bei Verwendung mit ValidateScript$PSItem ist der Wert des aktuellen Objekts, das überprüft wird. Wenn die Variable oder der Parameterwert ein Array ist, wird der Scriptblock einmal für jedes Objekt im Array mit $PSItem dem aktuellen Objekt aufgerufen.

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.

In diesem Beispiel wird der Scriptblock für das ValidateScript-Attribut einmal für jeden Wert ausgeführt, der an den Parameter Number übergeben wird, und gibt einen Fehler zurück, wenn ein Beliebiger Wert nicht einmal ist.

Die Add-EvenNumber Funktion addiert die gültigen Eingabenummern und gibt die Summe zurück.

Das Skriptblock des Ersetzungsoperators -replace

Ab PowerShell 6 können Sie beim Aufrufen des Ersetzungsoperatorsund Definieren eines Ersetzungsskriptblocks verwenden$PSItem. Wenn Sie dies tun, ist der Wert des $PSItem Werts der aktuellen Übereinstimmung.

$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

In diesem Beispiel ersetzt der Ersetzungsskriptblock die ursprüngliche Datumszeichenfolge durch das Standardformat für die aktuelle Kultur, indem er den Wert in "datetime" umgibt.

Weitere Informationen