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-Object
cmdlet - 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.