about_PSItem
Descrizione breve
Variabile automatica che contiene l'oggetto corrente nell'oggetto pipeline.
Descrizione lunga
PowerShell include la $PSItem
variabile e il relativo alias, $_
, come variabili automatiche in scriptblock che elaborano l'oggetto corrente, ad esempio nella pipeline. Questo articolo usa $PSItem
negli esempi, ma $PSItem
può essere sostituito con $_
in ogni esempio.
È possibile usare questa variabile nei comandi che eseguono un'azione su ogni oggetto in una pipeline.
Esistono alcuni casi d'uso comuni per $PSItem
:
- nello scriptblock per il parametro Process del
ForEach-Object
cmdlet - nello scriptblock per il parametro FilterScript del
Where-Object
cmdlet - nei metodi intrinseci ForEach e Where
- con parametri scriptblock delay-bind
- nei valori condizionali di un'istruzione
switch
e nei blocchi di script associati process
nel blocco di una funzione- in una
filter
definizione - nello scriptblock dell'attributo ValidateScript
Il resto di questo articolo include esempi di utilizzo $PSItem
per questi casi d'uso.
Processo ForEach-Object
Il cmdlet ForEach-Object è progettato per operare su oggetti nella pipeline, eseguendo lo scriptblock del parametro Process una volta per ogni oggetto nella pipeline.
È possibile usare $PSItem
nello scriptblock del parametro Process , ma non negli script dei parametri Begin o End . Se si fa riferimento $PSItem
negli script del parametro Begin o End , il valore è $null
dovuto al fatto che questi scriptblock non operano su ogni oggetto nella pipeline.
$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
Il cmdlet Where-Object è progettato per filtrare gli oggetti nella pipeline.
È possibile usare $PSItem
nello scriptblock del parametro FilterScript , che viene eseguito una sola volta per ogni oggetto di input nella pipeline.
1, 2, 3 | Where-Object -FilterScript { ($PSItem % 2) -eq 0 }
2
In questo esempio, FilterScript verifica se l'oggetto corrente è pari, filtrando eventuali valori dispari e restituisce solo 2
dall'elenco originale.
Metodi ForEach e Where
Sia i metodi intrinseci ForEach che Where per le matrici accettano uno scriptblock come parametro di input. È possibile usare in $PSItem
tali blocchi di script per accedere all'oggetto corrente.
@('a', 'b', 'c').ForEach({ $PSItem.ToUpper() }).Where({ $PSItem -ceq 'B' })
B
In questo esempio, lo scriptblock del metodo ForEach maiuscola l'oggetto corrente. Quindi, lo scriptblock del metodo Where restituisce solo B
.
Parametri scriptblock di associazione ritardata
I blocchi di script di associazione ritardata consentono di usare $PSItem
per definire i parametri per un cmdlet con pipeline prima di eseguirlo.
dir config.log | Rename-Item -NewName { "old_$($_.Name)" }
Switch statement scriptblocks
Nelle istruzioni switch è possibile usare $PSItem
sia negli script di azione che negli script di condizione delle istruzioni.
$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 questo esempio, lo scriptblock della condizione dell'istruzione controlla se l'oggetto corrente è pari. In caso affermativo, lo script di azione associato genera un messaggio che indica che l'oggetto corrente è pari.
Lo script di azione per la default
condizione restituisce un messaggio che indica che l'oggetto corrente è dispari.
Blocchi di processi di funzione
Quando si definisce una funzione, è possibile usare $PSItem
nella definizione del process
blocco ma non nelle definizioni di begin
blocchi o end
. Se si fa riferimento $PSItem
nei begin
blocchi o end
, il valore è $null
dovuto al fatto che tali blocchi non operano su ogni oggetto nella pipeline.
Quando si usa $PSItem
nella definizione del process
blocco, il valore è l'oggetto corrente se la funzione viene chiamata nella pipeline e in caso contrario $null
.
function Add-One {
process { $PSItem + 1 }
}
1, 2, 3 | Add-One
2
3
4
Suggerimento
Anche se è possibile usare $PSItem
nelle funzioni avanzate, c'è poco motivo per farlo. Se si intende ricevere input dalla pipeline, è consigliabile definire i parametri con uno degli ValueFromPipeline*
argomenti per l'attributo Parameter .
L'uso dell'attributo Parameter e dell'associazione di cmdlet per le funzioni avanzate rende l'implementazione più esplicita e prevedibile rispetto all'elaborazione dell'oggetto corrente per ottenere i valori necessari.
Un buon uso di $PSItem
nelle funzioni avanzate consiste nell'esaminare l'oggetto corrente stesso per il debug o la registrazione quando la funzione ha più parametri che accettano l'input dalla pipeline.
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
}
}
Questa funzione di esempio restituisce una matrice di oggetti JSON con un messaggio e un timestamp. Quando viene chiamato in una pipeline, usa la proprietà Message dell'oggetto corrente per ogni voce. Scrive anche la rappresentazione JSON dell'oggetto corrente nel flusso dettagliato, in modo da poter visualizzare l'input effettivo rispetto ai log di output.
$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)\/"
}
]
Definizioni di filtro
È possibile usare $PSItem
nell'elenco di istruzioni della definizione di un filtro.
Quando si usa $PSItem
in una filter
definizione, il valore è l'oggetto corrente se il filtro viene chiamato nella pipeline e in caso contrario $null
.
filter Test-IsEven { ($PSItem % 2) -eq 0 }
1, 2, 3 | Test-IsEven
False
True
False
In questo esempio il Test-IsEven
filtro restituisce $true
se l'oggetto corrente è un numero pari e $false
, in caso contrario, .
Scriptblock dell'attributo ValidateScript
È possibile usare $PSItem
nello scriptblock di un attributo ValidateScript .
Se usato con ValidateScript, $PSItem
è il valore dell'oggetto corrente da convalidare. Quando il valore della variabile o del parametro è una matrice, lo scriptblock viene chiamato una volta per ogni oggetto nella matrice con $PSItem
come oggetto corrente.
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
In questo esempio lo scriptblock per l'attributo ValidateScript viene eseguito una sola volta per ogni valore passato al parametro Number , restituendo un errore se un valore non è pari.
La Add-EvenNumber
funzione aggiunge i numeri di input validi e restituisce il totale.