about_PSItem

Krótki opis

Zmienna automatyczna zawierająca bieżący obiekt w obiekcie potoku.

Długi opis

Program PowerShell zawiera zmienną $PSItem i jej alias , $_jako zmienne automatyczne w skryptach, które przetwarzają bieżący obiekt, na przykład w potoku. W tym artykule użyto $PSItem w przykładach, ale $PSItem można go zastąpić $_ w każdym przykładzie.

Tej zmiennej można używać w poleceniach, które wykonują akcję na każdym obiekcie w potoku.

Istnieje kilka typowych przypadków użycia dla programu $PSItem:

  • w bloku skryptu dla parametru ForEach-ObjectProcesu polecenia cmdlet
  • w bloku skryptu dla parametru Where-Object FilterScript polecenia cmdlet
  • w metodach wewnętrznych ForEach i Where
  • z parametrami delay-bind scriptblock
  • switch w wartościach warunkowych instrukcji i skojarzonych blokach skryptów
  • process w bloku funkcji
  • filter w definicji
  • w bloku skryptu atrybutu ValidateScript

W pozostałej części tego artykułu przedstawiono przykłady użycia $PSItem dla tych przypadków użycia.

Proces ForEach-Object

Polecenie cmdlet ForEach-Object zostało zaprojektowane tak, aby działało na obiektach w potoku, wykonując skrypt parametru Process raz dla każdego obiektu w potoku.

Można użyć $PSItem w bloku skryptu parametru Procesu , ale nie w skryptach parametru Początek lub Koniec . Jeśli odwołujesz się $PSItem do skryptów parametru Początek lub Koniec , wartość jest $null , ponieważ te bloki skryptów nie działają na każdym obiekcie w potoku.

$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

Polecenie cmdlet Where-Object jest przeznaczone do filtrowania obiektów w potoku.

Można użyć $PSItem w skrypcie parametru FilterScript , który jest wykonywany raz dla każdego obiektu wejściowego w potoku.

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

W tym przykładzie funkcja FilterScript sprawdza, czy bieżący obiekt jest równomierny, odfiltrowuje wszystkie nieparzyste wartości i zwraca tylko 2 z oryginalnej listy.

Metody ForEach i Where

Metody wewnętrzne ForEach i Where dla tablic przyjmują blok skryptu jako parametr wejściowy. Możesz użyć $PSItem elementu w tych skryptach, aby uzyskać dostęp do bieżącego obiektu.

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

W tym przykładzie blok scriptblock metody ForEach zawiera wielkie litery bieżącego obiektu. Następnie skryptblock metody Where zwraca tylko B.

Parametry blokady skryptu powiązanego z opóźnieniem

Funkcja Delay-bind scriptblocks umożliwia $PSItem definiowanie parametrów dla polecenia cmdlet potoku przed jego wykonaniem.

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

Bloki skryptów instrukcji Switch

W instrukcjach switch można użyć $PSItem zarówno skryptów akcji, jak i skryptów warunku instrukcji.

$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

W tym przykładzie skrypt warunku instrukcji sprawdza, czy bieżący obiekt jest równomierny. Jeśli jest to równe, skojarzony skrypt akcji bloku zwraca komunikat wskazujący, że bieżący obiekt jest równomierny.

Blok skryptu akcji dla default warunku zwraca komunikat wskazujący, że bieżący obiekt jest dziwny.

Bloki procesów funkcji

Podczas definiowania funkcji można użyć $PSItem jej w process definicji bloku, ale nie w begin definicjach bloków lub end. Jeśli odwołujesz się $PSItem do begin bloków lub end , wartość jest $null tym, że te bloki nie działają na każdym obiekcie w potoku.

W przypadku użycia $PSItem w process definicji bloku wartość to bieżący obiekt, jeśli funkcja jest wywoływana w potoku, a w przeciwnym razie $null.

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

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

Napiwek

Chociaż można używać $PSItem w funkcjach zaawansowanych, niewiele jest powodów, aby to zrobić. Jeśli zamierzasz odbierać dane wejściowe z potoku, najlepiej zdefiniować parametry z jednym z ValueFromPipeline* argumentów atrybutu Parametr .

Użycie atrybutu parametru i powiązania polecenia cmdlet dla funkcji zaawansowanych sprawia, że implementacja jest bardziej jawna i przewidywalna niż przetwarzanie bieżącego obiektu w celu uzyskania wymaganych wartości.

Jedną z dobrych funkcji $PSItem zaawansowanych jest sprawdzenie bieżącego obiektu w celu debugowania lub rejestrowania, gdy funkcja ma wiele parametrów, które pobierają dane wejściowe z potoku.

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

Ta przykładowa funkcja generuje tablicę obiektów JSON z znacznikiem czasu i komunikatem. Wywołana w potoku używa właściwości Message bieżącego obiektu dla każdego wpisu. Zapisuje również reprezentację JSON bieżącego obiektu w pełnym strumieniu, dzięki czemu można zobaczyć rzeczywiste dane wejściowe w porównaniu z dziennikami wyjściowymi.

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

Definicje filtrów

Możesz użyć $PSItem na liście instrukcji definicji filtru.

W przypadku użycia $PSItem w filter definicji wartość jest bieżącym obiektem, jeśli filtr jest wywoływany w potoku i w przeciwnym razie $null.

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

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

W tym przykładzie Test-IsEven filtr zwraca dane wyjściowe $true , jeśli bieżący obiekt jest liczbą parzystą, a $false jeśli tak nie jest.

Blok skryptów atrybutu ValidateScript

Możesz użyć $PSItem w bloku skryptowym atrybutu ValidateScript . W przypadku użycia z językiem ValidateScript$PSItem wartość bieżącego obiektu jest weryfikowana. Gdy zmienna lub wartość parametru jest tablicą, blok scriptblock jest wywoływany raz dla każdego obiektu w tablicy z $PSItem jako bieżącym obiektem.

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

W tym przykładzie blok skryptu dla atrybutu ValidateScript jest uruchamiany raz dla każdej wartości przekazanej do parametru Number , zwracając błąd, jeśli jakakolwiek wartość nie jest nawet.

Funkcja Add-EvenNumber dodaje prawidłowe liczby wejściowe i zwraca sumę.

Zobacz też