about_PSItem

Descripción breve

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

Descripción larga

PowerShell incluye la $PSItem variable y su alias, , $_como variables automáticas en los bloques de script que procesan el objeto actual, como en la canalización. En este artículo se usa $PSItem en los ejemplos, pero $PSItem se puede reemplazar por $_ en cada ejemplo.

Puede usar esta variable en comandos que realizan una acción en cada objeto de una canalización.

Hay algunos casos de uso comunes para $PSItem:

  • en el scriptblock para el parámetro Process del ForEach-Objectcmdlet
  • en el scriptblock para el parámetro FilterScript del Where-Object cmdlet
  • 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 los bloques de script asociados
  • en el process bloque de una función
  • en una filter definición
  • en el scriptblock del atributo ValidateScript
  • en el scriptblock del operando de sustitución del -replace operador

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

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

Parámetros de scriptblock 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)" }

Bloqueos de script de instrucción 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 scriptblock de condición de instrucción comprueba si el objeto actual es par. Si es incluso, el scriptblock de acción asociado genera un mensaje que indica que el objeto actual es incluso.

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

Bloques 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 de process bloque, 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 uno de los ValueFromPipeline* argumentos del 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 bloque de scripts del atributo ValidateScript

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 scripts de sustitución del operador -replace

A partir de PowerShell 6, puede usar $PSItem al llamar al operador replace y definir un bloque de scripts de sustitución. 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.

Consulte también