Поделиться через


about_PSItem

Краткое описание

Автоматическая переменная, содержащая текущий объект в объекте конвейера.

Подробное описание

PowerShell включает $PSItem переменную и его псевдоним, $_как автоматические переменные в скриптблоках, обрабатывающих текущий объект, например в конвейере. Эта статья используется $PSItem в примерах, но $PSItem может быть заменена $_ на каждый пример.

Эту переменную можно использовать в командах, выполняющих действие для каждого объекта в конвейере.

Существует несколько распространенных вариантов использования:$PSItem

  • в файле scriptblock для параметра Process командлета ForEach-Object
  • в блоке скрипта для параметра FilterScript командлета Where-Object
  • в встроенных методах ForEach и Where
  • с параметрами скрипта с задержкой привязки
  • switch в условных значениях инструкции и связанных скриптах
  • process в блоке функции
  • в определении filter
  • в блоке скрипта атрибута ValidateScript
  • в блоке скрипта подстановки оператора -replace

Остальная часть этой статьи содержит примеры использования $PSItem для этих вариантов использования.

Процесс forEach-Object

Командлет ForEach-Object предназначен для работы с объектами в конвейере, выполняя блок скрипта параметра Process один раз для каждого объекта в конвейере.

Вы можете использовать $PSItem в блоке скриптов параметра Process, но не в блоках скриптов начального или конечного параметра. Если вы ссылаетесь $PSItem на скрипты начального или конечного параметров, значение заключается $null в том, что эти блоки скриптов не работают с каждым объектом в конвейере.

$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

Командлет Where-Object предназначен для фильтрации объектов в конвейере.

Можно использовать $PSItem в блоке скрипта параметра FilterScript, который выполняется один раз для каждого входного объекта в конвейере.

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

В этом примере FilterScript проверяет, является ли текущий объект даже, отфильтровывая какие-либо нечетные значения, и возвращается только 2 из исходного списка.

Методы ForEach и Where

Встроенные методы ForEach и Where для массивов принимают скриптблок в качестве входного параметра. Эти блоки скриптов можно использовать $PSItem для доступа к текущему объекту.

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

В этом примере блок скрипта метода ForEach содержит верхние регистры текущего объекта. Затем возвращается только Bблок скрипта метода Where.

Параметры скрипта с задержкой привязки

Блоки скриптов с задержкой привязки позволяют определять $PSItem параметры для конвейерного командлета перед его выполнением.

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

Переключение блоков скриптов инструкций

В инструкциях switch можно использовать $PSItem как в сценариях действий, так и в сценариях условий инструкций.

$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

В этом примере скрипт условия инструкции проверяет, является ли текущий объект даже. Если это даже, связанный скрипт действия выводит сообщение, указывающее, что текущий объект даже.

Блок скрипта действия для default условия выводит сообщение, указывающее, что текущий объект нечетен.

Блоки процессов функций

При определении функции можно использовать $PSItem в process определении блока, но не в begin end определениях блоков. Если ссылаются $PSItem в begin блоках или end блоках, это значение связано $null с тем, что эти блоки не работают над каждым объектом в конвейере.

При использовании $PSItem в process определении блока значение является текущим объектом, если функция вызывается в конвейере и в противном случае $null.

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

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

Совет

Хотя вы можете использовать $PSItem в расширенных функциях, есть мало причин для этого. Если вы планируете получать входные данные из конвейера, рекомендуется определить параметры с одним из ValueFromPipeline* аргументов для атрибута Параметра .

Использование атрибута параметра и привязки командлета для расширенных функций делает реализацию более явной и прогнозируемой, чем обработка текущего объекта для получения необходимых значений.

Одним из хороших способов использования расширенных $PSItem функций является проверка текущего объекта для отладки или ведения журнала при наличии нескольких параметров, которые принимают входные данные из конвейера.

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

В этом примере функция выводит массив объектов JSON с сообщением и меткой времени. При вызове в конвейере используется свойство Message текущего объекта для каждой записи. Он также записывает представление JSON текущего объекта в подробный поток, чтобы увидеть фактические входные данные по сравнению с выходными журналами.

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

Определения фильтров

Вы можете использовать $PSItem в списке инструкций определения фильтра.

При использовании $PSItem в filter определении значение является текущим объектом, если фильтр вызывается в конвейере и в противном случае $null.

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

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

В этом примере Test-IsEven фильтр выводит, $true если текущий объект является четным числом, а $false если это не так.

Блок скрипта атрибута ValidateScript

Вы можете использовать $PSItem в блоке скриптов атрибута ValidateScript . При использовании с ValidateScript$PSItem используется значение проверяемого текущего объекта. Если переменная или значение параметра является массивом, блок скрипта вызывается один раз для каждого объекта в массиве с $PSItem текущим объектом.

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.

В этом примере блок скрипта для атрибута ValidateScript выполняется один раз для каждого значения, переданного параметру Number , возвращая ошибку, если какое-либо значение не даже.

Функция Add-EvenNumber добавляет допустимые входные числа и возвращает общее значение.

Блок скрипта подстановки оператора -replace

Начиная с PowerShell 6, можно использовать $PSItem при вызове оператора замены и определении подстановки скрипта. При этом значение $PSItem равно значению текущего совпадения.

$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

В этом примере блок скрипта подстановки заменяет исходную строку даты форматом по умолчанию для текущего языка и региональных параметров путем приведения значения к дате.

См. также