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-Objectcmdlet
  • 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
  • nell'operando di sostituzione scriptblock dell'operatore -replace

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:
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 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.

Scriptblock di sostituzione dell'operatore -replace

A partire da PowerShell 6, è possibile usare $PSItem quando si chiama l'operatore replace e si definisce un blocco di script di sostituzione. Quando si esegue questa operazione, 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.

Vedi anche