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 $PSItem
programu :
- w skrybloku parametru
ForEach-Object
Procesu polecenia cmdlet - w bloku skryptów 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 skryptachprocess
w bloku funkcjifilter
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 $PSItem
begin
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.