Condividi tramite


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-Objectcmdlet
  • 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.

Vedi anche