about_PSItem
Descrição breve
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-Object
cmdlet - no scriptblock do parâmetro FilterScript do
Where-Object
cmdlet - nos métodos intrínsecos ForEach e Where
- com parâmetros scriptblock de ligação de atraso
- nos valores condicionais de uma
switch
instrução e ScriptBlocks associados process
no bloco de uma função- em uma
filter
definição - no bloco de script do atributo ValidateScript
- no scriptblock do operando de substituição do
-replace
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 somente 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 maiúsculas do objeto atual. Em seguida, o scriptblock do método Where retorna somente B
.
Parâmetros de bloqueio de script de ligação de atraso
Os blocos de script de vinculação de atraso permitem que você defina $PSItem
parâmetros para um cmdlet de pipeline antes de executá-lo.
dir config.log | Rename-Item -NewName { "old_$($_.Name)" }
Alternar scriptblocks de instrução
Em instruções switch, você pode usar $PSItem
em scriptblocks de ação e scriptblocks de condição de instrução.
$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, o scriptblock de condição de instrução verifica se o objeto atual é uniforme. Se for par, o scriptblock de ação associado gera uma mensagem indicando que o objeto atual é par.
O scriptblock 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 begin
definições de bloco ou end
de bloco. 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
Dica
Embora você possa usar $PSItem
em funções avançadas, há poucos motivos para fazê-lo. Se você pretende receber entrada do pipeline, é melhor definir parâmetros com um dos ValueFromPipeline*
argumentos para o atributo Parameter .
Usar o atributo Parameter e a associação de cmdlet para funções avançadas torna a implementação mais explícita e previsível do que processar o 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 scriptblock para o atributo ValidateScript é executado uma vez para cada valor passado para o parâmetro Number , retornando um erro se qualquer 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 replace e definir um scriptblock de substituição. Quando você fizer isso, o valor de $PSItem
é o valor da 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 scriptblock de substituição substitui a cadeia de caracteres de data original pelo formato padrão para a cultura atual, convertendo o valor para datetime.