Compartir a través de


about_PSItem

Descripción breve

Variable automática que contiene el objeto actual en el objeto de canalización.

Descripción larga

PowerShell incluye dos variables automáticas$_ y "$PSItem" que hacen referencia al objeto actual de la canalización.

$PSItem se agregó a PowerShell en un intento de proporcionar un significado más claro al nombre de la variable. Sin embargo, en la práctica, la forma $_ de subrayado de signo de dólar se usa con más frecuencia.

Aunque en este artículo se usa $PSItem en los ejemplos, $PSItem se puede reemplazar por $_ en cada ejemplo. $_ es el uso preferido.

Hay algunos casos de uso comunes para $PSItem:

  • En el bloque de scripts para el parámetro Process del cmdlet ForEach-Object.
  • En el bloque de scripts para el parámetro FilterScript del cmdlet Where-Object
  • En los métodos intrínsecos ForEach y Where
  • con parámetros de scriptblock de enlace retrasado
  • En los valores condicionales de una switch instrucción y las instrucciones asociadas
  • En el bloque de instrucciones process de una función
  • En una definición filter
  • En el bloque de scripts del atributo ValidateScript
  • En el bloque de instrucciones de un catch
  • En el bloque de scripts del operando de sustitución del operador -replace

El resto de este artículo incluye ejemplos de uso $PSItem para estos casos de uso.

parámetro process de ForEach-Object

El cmdlet ForEach-Object está diseñado para operar en objetos de la canalización, ejecutando el bloque de scripts del parámetro Process una vez para cada objeto de la canalización.

Puede usar $PSItem en el scriptblock del parámetro Process , pero no en los bloques de script de parámetro Begin o End . Si hace referencia $PSItem a los scriptblocks del parámetro Begin o End , el valor se debe $null a que esos bloques de script no funcionan en cada objeto de la canalización.

$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

El cmdlet Where-Object está diseñado para filtrar objetos en la canalización.

Puede usar $PSItem en el scriptblock del parámetro FilterScript , que se ejecuta una vez para cada objeto de entrada de la canalización.

1, 2, 3 | Where-Object -FilterScript { ($PSItem % 2) -eq 0 }
2

En este ejemplo, FilterScript comprueba si el objeto actual es par, filtrando los valores impares y devuelve solo 2 de la lista original.

Métodos ForEach y Where

Los métodos intrínsecos ForEach y Where para las matrices toman un scriptblock como parámetro de entrada. Puede usar en $PSItem esos bloques de script para tener acceso al objeto actual.

@('a', 'b', 'c').ForEach({ $PSItem.ToUpper() }).Where({ $PSItem -ceq 'B' })
B

En este ejemplo, el bloque de scripts del método ForEach en mayúsculas el objeto actual. A continuación, el scriptblock del método Where devuelve solo B.

Bloqueos de script de enlace retrasado

Los bloques de script de enlace retrasado permiten usar $PSItem para definir parámetros para un cmdlet canalización antes de ejecutarlo.

dir config.log | Rename-Item -NewName { "old_$($_.Name)" }

Instrucciones Switch

En las instrucciones switch, puede usar $PSItem en los bloques de scriptblocks de acción y en los scriptblocks de condición de instrucción.

$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

En este ejemplo, el bloque de instrucciones condition comprueba si el objeto actual es par. Si es incluso, el bloque de instrucciones de acción asociada genera un mensaje que indica que el objeto actual es incluso.

El bloque de instrucción action de la default condición genera un mensaje que indica que el objeto actual es impar.

Bloques de instrucciones de proceso de función

Al definir una función, puede usar $PSItem en la definición de process bloque, pero no en las begin definiciones de bloque o end . Si hace referencia $PSItem a en los begin bloques o end , el valor se debe $null a que esos bloques no operan en cada objeto de la canalización.

Cuando se usa $PSItem en la definición del process bloque de instrucciones, el valor es el objeto actual si se llama a la función en la canalización y, de lo contrario $null, .

function Add-One {
    process { $PSItem + 1 }
}

1, 2, 3 | Add-One
2
3
4

Sugerencia

Aunque puede usar $PSItem en funciones avanzadas, hay poca razón para hacerlo. Si piensa recibir la entrada de la canalización, es mejor definir parámetros con el uso de los ValueFromPipeline argumentos o ValueFromPipelineByPropertyName en el atributo Parameter .

El uso del atributo Parameter y el enlace de cmdlets para funciones avanzadas hace que la implementación sea más explícita y predecible que procesar el objeto actual para obtener los valores necesarios.

Un buen uso de $PSItem en funciones avanzadas es inspeccionar el propio objeto actual para depurar o registrar cuando la función tiene varios parámetros que toman la entrada de la canalización.

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
    }
}

Esta función de ejemplo genera una matriz de objetos JSON con un mensaje y una marca de tiempo. Cuando se llama en una canalización, usa la propiedad Message del objeto actual para cada entrada. También escribe la representación JSON del propio objeto actual en el flujo detallado, por lo que puede ver la entrada real en comparación con los registros de salida.

$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)\/"
    }
]

Definiciones de filtro

Puede usar $PSItem en la lista de instrucciones de la definición de un filtro.

Cuando se usa $PSItem en una filter definición, el valor es el objeto actual si se llama al filtro en la canalización y, de lo contrario $null, .

filter Test-IsEven { ($PSItem % 2) -eq 0 }

1, 2, 3 | Test-IsEven
False
True
False

En este ejemplo, el Test-IsEven filtro genera $true si el objeto actual es un número par y $false si no lo es.

El atributo ValidateScript ScriptBlock

Puede usar $PSItem en el scriptblock de un atributo ValidateScript . Cuando se usa con ValidateScript, $PSItem es el valor del objeto actual que se va a validar. Cuando el valor de la variable o del parámetro es una matriz, se llama a scriptblock una vez para cada objeto de la matriz con $PSItem como objeto actual.

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.

En este ejemplo, el scriptblock para el atributo ValidateScript se ejecuta una vez para cada valor pasado al parámetro Number , devolviendo un error si algún valor no es ni siquiera.

La Add-EvenNumber función agrega los números de entrada válidos y devuelve el total.

Bloque de catch instrucciones

Dentro de un catch bloque de instrucciones, $PSItem contiene el error actual. El objeto es de tipo ErrorRecord.

try { NonsenseString }
catch {
    Write-Host "An error occurred:"
    Write-Host $PSItem
}

Al ejecutar este script, se devuelve el siguiente resultado:

An error occurred:
The term 'NonsenseString' is not recognized as the name of a cmdlet, function,
script file, or operable program. Check the spelling of the name, or if a path
was included, verify that the path is correct and try again.

Para ver más ejemplos, consulte la sección Acceso a la información de excepciones en about_Try_Catch_Finally.

Bloque -replace de scripts de sustitución del operador

A partir de PowerShell 6, puede usar $PSItem al llamar al operador -replace y definir un bloque de scripts de sustitución de . Cuando lo hace, el valor de $PSItem es el valor de la coincidencia actual.

$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

En este ejemplo, el bloque de scripts de sustitución reemplaza la cadena de fecha original por el formato predeterminado de la referencia cultural actual mediante la conversión del valor a datetime.

Cambio del valor de $PSItem

Puede cambiar el valor de $PSItem asignando un nuevo valor a él. Sin embargo, si lo hace, puede cambiar el comportamiento esperado de cualquier código que se base en $PSItem. Considere el ejemplo siguiente. Normalmente, la switch instrucción procesaría todos los valores de la matriz $names. Dado que el valor de $PSItem se cambia dentro del bloque de instrucciones de acción, la switch instrucción procesa solo el primer valor.

$names = 'Alice', 'Charlie'
switch ($names) {
    Alice   { "$PSItem says 'Hello!'"; $PSItem = 'Bob' }
    Bob     { "$PSItem says 'Goodbye.'"; $PSItem = 'Charlie'; break }
    Charlie { "$PSItem says 'How are you?'" }
}

Cuando la switch instrucción evalúa el primer valor, Alice, coincide con la primera condición y ejecuta el bloque de instrucciones de acción asociada. Dentro de ese bloque, el valor de $PSItem se cambia a Bob, que también afecta a la evaluación de la switch instrucción .

Alice says 'Hello!'
Bob says 'Goodbye.'

Debe evitar cambiar el valor de $PSItem.

Consulte también