次の方法で共有


about_PSItem

簡単な説明

パイプライン オブジェクト内の現在のオブジェクトを含む自動変数。

詳細な説明

PowerShell には、パイプラインなど、現在のオブジェクトを処理するスクリプト ブロックに、自動変数として$PSItem変数とそのエイリアス ($_) が含まれています。 この記事では、例の $PSItem を使用しますが、 $PSItem はすべての例で $_ に置き換えることができます。

この変数は、パイプライン内のすべてのオブジェクトに対してアクションを実行するコマンドで使用できます。

$PSItemには、いくつかの一般的なユース ケースがあります。

  • ForEach-Objectcmdlet の Process パラメーターの scriptblock 内
  • Where-Object コマンドレットの FilterScript パラメーターの scriptblock 内
  • 組み込みメソッド ForEachWhere
  • 遅延バインド scriptblock パラメーター
  • switch ステートメントの条件付き値と関連するスクリプト ブロック内
  • 関数の process ブロック内
  • filter定義内
  • ValidateScript 属性の scriptblock 内
  • -replace演算子の置換オペランドスクリプトブロック内

この記事の残りの部分には、これらのユース ケースに $PSItem を使用する例が含まれています。

ForEach-Object プロセス

ForEach-Object コマンドレットは、パイプライン内のオブジェクトを操作し、パイプライン内のすべてのオブジェクトに対して Process パラメーターの scriptblock を 1 回実行するように設計されています。

Process パラメーターのスクリプトブロックでは$PSItemを使用できますが、Begin または End パラメータースクリプトブロックでは使用できません。 Begin または End パラメータースクリプトブロックで$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は、パイプライン内の入力オブジェクトごとに 1 回実行される FilterScript パラメーターの scriptblock で使用できます。

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

この例では、 FilterScript は、現在のオブジェクトが偶数かどうかを確認し、奇数の値をフィルターで除外し、元のリストから 2 のみを返します。

ForEach メソッドと Where メソッド

配列の ForEachWhere の両方の組み込みメソッドは、スクリプトブロックを入力パラメーターとして受け取ります。 これらのスクリプト ブロックの $PSItem を使用して、現在のオブジェクトにアクセスできます。

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

この例では、 ForEach メソッドの scriptblock によって現在のオブジェクトが大文字になります。 次に、 Where メソッドの scriptblock は Bのみを返します。

遅延バインド scriptblock パラメーター

遅延バインド スクリプトブロック を使用すると $PSItem を使用して、パイプライン化されたコマンドレットのパラメーターを定義してから実行できます。

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

Switch ステートメントのスクリプトブロック

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

この例では、ステートメント条件 scriptblock は、現在のオブジェクトが偶数かどうかをチェックします。 偶数の場合、関連付けられているアクション scriptblock は、現在のオブジェクトが偶数であることを示すメッセージを出力します。

default条件のアクション スクリプトブロックは、現在のオブジェクトが奇数であることを示すメッセージを出力します。

関数プロセス ブロック

関数を定義する場合processブロック定義では$PSItemを使用できますが、beginまたはendブロック定義では使用できません。 beginまたはend ブロック内の$PSItemを参照する場合、これらのブロックはパイプライン内の各オブジェクトで動作しないため、値は$nullされます。

process ブロック定義で$PSItemを使用する場合、関数がパイプラインで呼び出され、それ以外の場合は$null場合、値は現在のオブジェクトになります。

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

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

ヒント

$PSItem関数で使用できますがそうする理由はほとんどありません。 パイプラインから入力を受け取る場合は、Parameter 属性のValueFromPipeline*引数のいずれかを使用してパラメーターを定義することをお勧めします。

高度な関数に対して Parameter 属性とコマンドレット バインドを使用すると、現在のオブジェクトを処理して必要な値を取得するよりも、実装がより明示的かつ予測可能になります。

高度な関数での $PSItem の優れた用途の 1 つは、関数にパイプラインからの入力を受け取る複数のパラメーターがある場合に、デバッグまたはログ記録のために現在のオブジェクト自体を検査することです。

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

フィルター定義

filterの定義のステートメント リストで$PSItemを使用できます。

filter定義で$PSItemを使用する場合、フィルターがパイプラインで呼び出され、それ以外の場合は$null場合、値は現在のオブジェクトになります。

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

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

この例では、現在のオブジェクトが偶数の場合は Test-IsEven フィルター出力が $true され、そうでない場合は $false されます。

ValidateScript 属性のスクリプトブロック

$PSItemは、ValidateScript 属性の scriptblock で使用できます。 ValidateScript で使用する場合、$PSItemは検証中の現在のオブジェクトの値です。 変数またはパラメーター値が配列の場合、 $PSItem を現在のオブジェクトとして使用して、配列内の各オブジェクトに対して scriptblock が 1 回呼び出されます。

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 属性の scriptblock は、 Number パラメーターに渡された値ごとに 1 回実行され、値が偶数でない場合はエラーが返されます。

Add-EvenNumber関数は、有効な入力番号を追加し、合計を返します。

replace 演算子の置換スクリプトブロック

PowerShell 6 以降では、replace 演算子を呼び出し、substitution scriptblock を定義するときに、$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

この例では、置換スクリプトブロックは、値を datetime にキャストすることで、元の日付文字列を現在のカルチャの既定の形式に置き換えます。

関連項目