Udostępnij za pośrednictwem


about_PSItem

Krótki opis

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

Długi opis

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

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

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

  • w skrybloku parametru ForEach-ObjectProcesu polecenia cmdlet
  • w bloku skryptów parametruWhere-Object FilterScript polecenia cmdlet
  • w metodach wewnętrznych ForEach i Where
  • z parametrami delay-bind scriptblock
  • switch w wartościach warunkowych instrukcji i skojarzonych skryptach
  • process w bloku funkcji
  • filter w definicji
  • w skrypcie atrybutu ValidateScript
  • w skrypcie operandu podstawień -replace operator

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 skryptblock parametru Process raz dla każdego obiektu w potoku.

Można użyć $PSItem w bloku skryptu parametru procesu , ale nie w blokach skryptów parametru Begin lub End . Jeśli odwołujesz się $PSItem do skryptów parametrów Begin lub End , wartość to $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 zostało zaprojektowane 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 skrypt FilterScript sprawdza, czy bieżący obiekt jest równomierny, filtrując wszelkie nieparzyste wartości i zwracając tylko 2 z oryginalnej listy.

Metody ForEach i Where

Metody wewnętrzne forEach i Where dla tablic przyjmują blok skryptu jako parametr wejściowy. W tych skryptach można użyć $PSItem elementu w celu uzyskania dostępu do bieżącego obiektu.

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

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

Opóźnione parametry skryptblock

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

Switch scriptblocks instrukcji

W instrukcjach switch można użyć $PSItem zarówno w blokach skryptów akcji, jak i skryptach 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 skryptblock warunku instrukcji sprawdza, czy bieżący obiekt jest równy. Jeśli jest to równe, skojarzony skrypt akcji blokuje 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 procesu funkcji

Podczas definiowania funkcji można użyć $PSItem w process definicji bloku, ale nie w begin definicjach bloków lub end . Jeśli odwołujesz się do $PSItembegin bloków lub end , wartość to $null , ponieważ 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

Porada

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

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

Jednym z dobrych zastosowań $PSItem funkcji zaawansowanych jest sprawdzenie bieżącego obiektu na potrzeby 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. Po wywołaniu 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 filtruje dane wyjściowe $true , jeśli bieżący obiekt jest parzystą liczbą i $false jeśli nie jest.

Blok skryptu atrybutu ValidateScript

Można użyć $PSItem w skrypcie atrybutu ValidateScript . W przypadku użycia z elementem ValidateScript$PSItem jest wartością bieżącego obiektu, który jest weryfikowany. Gdy zmienna lub wartość parametru jest tablicą, blok skryptu 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:
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.

W tym przykładzie blok skryptu 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ę.

-replace operator's subskrypcja scriptblock

Począwszy od programu PowerShell 6, można użyć podczas $PSItem wywoływania operatora zastępowania i definiowania skryptu podstawienia. Gdy to zrobisz, wartość to wartość $PSItem bieżącego dopasowania.

$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

W tym przykładzie skrypt podstawiania zastępuje oryginalny ciąg daty domyślnym formatem bieżącej kultury przez rzutowanie wartości do daty/godziny.

Zobacz też