about_PSItem

簡単な説明

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

詳細な説明

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

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

次のような一般的なユース ケース $PSItemがいくつかあります。

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

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

ForEach-Object プロセス

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

Process パラメーターのスクリプト ブロックでは使用できますが、Begin または End パラメーターのスクリプトブロックでは使用$PSItemできません。 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 コマンドレットは、パイプライン内のオブジェクトをフィルター処理するように設計されています。

パイプライン内の入力オブジェクトごとに 1 回実行される FilterScript パラメーターのスクリプト ブロックで使用$PSItemできます。

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 メソッドのスクリプト ブロックによって現在のオブジェクトが大文字になります。 次に、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使用できますが、ブロック定義またはendブロック定義ではbegin使用$PSItemできません。 またはendブロックで参照$PSItemするbegin場合、値は、これらのブロックが$nullパイプライン内の各オブジェクトで動作しないためです。

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

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

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

ヒント

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

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

高度な関数の 1 つの優れた用途は、パイプラインから入力を受け取る複数の $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オブジェクトが偶数$falseでなければ、フィルターが出力$trueされます。

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

ValidateScript 属性の scriptblock で使用$PSItemできます。 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 属性のスクリプトブロックは Number パラメーターに渡された値ごとに 1 回実行され、値が偶数でない場合はエラーが返されます。

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

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

PowerShell 6 以降では、replace 演算子を呼び出し、置換スクリプト ブロックを定義するときに使用$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 にキャストすることで、元の日付文字列を現在のカルチャの既定の形式に置き換えます。

関連項目