about_PSItem

Breve descrição

A variável automática que contém o objeto atual no objeto de pipeline.

Descrição longa

O PowerShell inclui a $PSItem variável e seu alias, $_, como variáveis automáticas em blocos de script que processam o objeto atual, como no pipeline. Este artigo usa $PSItem nos exemplos, mas $PSItem pode ser substituído por $_ em todos os exemplos.

Você pode usar essa variável em comandos que executam uma ação em cada objeto em um pipeline.

Existem alguns casos de uso comuns para $PSItem:

  • no scriptblock para o parâmetro Process do ForEach-Objectcmdlet
  • no scriptblock para o parâmetro FilterScript do Where-Object cmdlet
  • nos métodos intrínsecos ForEach e Where
  • com parâmetros de bloqueio de scriptblock de vinculação de atraso
  • nos valores condicionais de uma switch instrução e scriptblocks associados
  • process no bloco de uma função
  • filter numa definição
  • no scriptblock do atributo ValidateScript
  • no bloco de script do operando de -replace substituição do operador

O restante deste artigo inclui exemplos de uso $PSItem para esses casos de uso.

Processo ForEach-Object

O cmdlet ForEach-Object foi projetado para operar em objetos no pipeline, executando o scriptblock do parâmetro Process uma vez para cada objeto no pipeline.

Você pode usar $PSItem no scriptblock do parâmetro Process, mas não nos scriptblocks do parâmetro Begin ou End. Se você fizer referência $PSItem nos scriptblocks do parâmetro Begin ou End , o valor será $null porque esses scriptblocks não operam em cada objeto no 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

O cmdlet Where-Object foi projetado para filtrar objetos no pipeline.

Você pode usar $PSItem no scriptblock do parâmetro FilterScript , que é executado uma vez para cada objeto de entrada no pipeline.

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

Neste exemplo, o FilterScript verifica se o objeto atual é par, filtrando quaisquer valores ímpares e retorna apenas 2 da lista original.

Métodos ForEach e Where

Os métodos intrínsecos ForEach e Where para matrizes usam um scriptblock como um parâmetro de entrada. Você pode usar o $PSItem nesses blocos de script para acessar o objeto atual.

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

Neste exemplo, o scriptblock do método ForEach coloca maiúsculas no objeto atual. Em seguida, o scriptblock do método Where retorna apenas B.

Parâmetros de scriptblock de vinculação de atraso

Os scriptblocks de vinculação de atraso permitem que você use $PSItem para definir parâmetros para um cmdlet pipelined antes de executá-lo.

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

Blocos de script de instrução Switch

Em instruções switch, você pode usar $PSItem em action scriptblocks e statement condition scriptblocks.

$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

Neste exemplo, a condição de instrução scriptblock verifica se o objeto atual é par. Se for par, o bloco de script de ação associado emite uma mensagem indicando que o objeto atual é par.

O bloco de script de ação para a default condição gera uma mensagem indicando que o objeto atual é ímpar.

Blocos de processo de função

Ao definir uma função, você pode usar $PSItem na definição de process bloco, mas não nas definições de begin bloco ou end . Se você fizer referência $PSItem nos begin blocos ou end , o valor será $null porque esses blocos não operam em cada objeto no pipeline.

Quando você usa $PSItem na definição de process bloco, o valor é o valor é o objeto atual se a função for chamada no pipeline e de outra forma $null.

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

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

Gorjeta

Embora você possa usar $PSItem em funções avançadas, há poucas razões para fazê-lo. Se você pretende receber entrada do pipeline, é melhor definir parâmetros com um dos ValueFromPipeline* argumentos para o atributo Parameter .

O uso do atributo Parameter e da associação de cmdlets para funções avançadas torna a implementação mais explícita e previsível do que o processamento do objeto atual para obter os valores necessários.

Um bom uso de $PSItem funções avançadas é inspecionar o próprio objeto atual para depuração ou registro em log quando a função tem vários parâmetros que recebem entrada do 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
    }
}

Esta função de exemplo gera uma matriz de objetos JSON com uma mensagem e um carimbo de data/hora. Quando chamado em um pipeline, ele usa a propriedade Message do objeto atual para cada entrada. Ele também grava a representação JSON do próprio objeto atual no fluxo detalhado, para que você possa ver a entrada real em comparação com os logs de saída.

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

Definições de filtro

Você pode usar $PSItem na lista de instruções da definição de um filtro.

Quando você usa $PSItem em uma filter definição, o valor é o objeto atual se o filtro for chamado no pipeline e de outra forma $null.

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

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

Neste exemplo, o Test-IsEven filtro gera saídas $true se o objeto atual for um número par e $false se não for.

O scriptblock do atributo ValidateScript

Você pode usar $PSItem no scriptblock de um atributo ValidateScript . Quando usado com ValidateScript, $PSItem é o valor do objeto atual que está sendo validado. Quando a variável ou o valor do parâmetro é uma matriz, o scriptblock é chamado uma vez para cada objeto na matriz com $PSItem como o objeto atual.

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.

Neste exemplo, o bloco de script para o atributo ValidateScript é executado uma vez para cada valor passado para o parâmetro Number , retornando um erro se algum valor não for par.

A Add-EvenNumber função adiciona os números de entrada válidos e retorna o total.

O scriptblock de substituição do operador -replace

A partir do PowerShell 6, você pode usar $PSItem ao chamar o operador de substituição e definir um bloco de script de substituição. Quando o fizer, o valor de é o valor da $PSItem correspondência atual.

$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

Neste exemplo, o bloco de script de substituição substitui a cadeia de caracteres de data original pelo formato padrão para a cultura atual, convertendo o valor para datetime.

Consulte também