about_PSItem
Breve descrizione
Variabile automatica contenente l'oggetto corrente nell'oggetto pipeline.
Descrizione lunga
PowerShell include la variabile e il $PSItem
relativo alias, , $_
come variabili automatiche in scriptblocks 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
:
- nel blocco script 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 di delay-bind
- nei valori condizionali di un'istruzione
switch
e nei blocchi script associati - nel
process
blocco di una funzione - in una
filter
definizione - nel blocco script dell'attributo ValidateScript
- nell'operando di sostituzione scriptblock dell'operatore
-replace
Il resto di questo articolo include esempi di uso per questi casi d'uso $PSItem
.
ForEach-Object Processo
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 di parametri 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 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 è uniforme, filtrando i valori dispari e restituisce solo 2
dall'elenco originale.
ForEach e Where metodi
Sia forEach che dove i metodi intrinseci per le matrici accettano uno scriptblock come parametro di input. È possibile usare in $PSItem
tali blocchi 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. Lo scriptblock del metodo Where restituisce solo B
.
Parametri scriptblock di associazione ritardata
Gli scriptblock 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 nei blocchi script delle istruzioni e negli script di condizione dell'istruzione.
$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 script di condizione dell'istruzione verifica se l'oggetto corrente è pari. Se è pari, lo script di azione associato genera un messaggio che indica che l'oggetto corrente è anche.
Lo script di azione per la default
condizione restituisce un messaggio che indica che l'oggetto corrente è strano.
Blocchi di processo della 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
ai 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 process
definizione del 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 l'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, quindi è possibile 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 delle istruzioni della definizione di un filtro.
Quando si usa in una filter
definizione, il valore è l'oggetto corrente se il filtro viene chiamato $PSItem
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 l'output $true
se l'oggetto corrente è un numero pari e $false
se non è.
Scriptblock dell'attributo ValidateScript
È possibile usare $PSItem
nello scriptblock di un attributo ValidateScript .
Se usato con ValidateScript, $PSItem
è il valore dell'oggetto corrente convalidato. Quando la variabile o il valore 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:
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 questo esempio lo scriptblock per l'attributo ValidateScript viene eseguito una volta per ogni valore passato al parametro Number , restituito un errore se un valore non è nemmeno.
La Add-EvenNumber
funzione aggiunge i numeri di input validi e restituisce il totale.
Script di sostituzione dell'operatore -replace
A partire da PowerShell 6, è possibile usare $PSItem
quando si chiama l'operatore di sostituzione e si definisce uno scriptblock di sostituzione. Quando si esegue, il valore di $PSItem
è il valore della corrispondenza corrente.
$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 questo esempio, lo scriptblock di sostituzione sostituisce la stringa di data originale con il formato predefinito per le impostazioni cultura correnti eseguendo il cast del valore in datetime.