about_PSItem
簡単な説明
パイプライン オブジェクト内の現在のオブジェクトを含む自動変数。
長い説明
PowerShell には、$_
現在のオブジェクト ($PSItem
パイプラインなど) を処理するスクリプトブロックの自動変数として、変数とそのエイリアス が含まれています。 この記事では、例で を使用 $PSItem
しますが $PSItem
、すべての例で を $_
に置き換えることができます。
この変数は、パイプライン内のすべてのオブジェクトに対してアクションを実行するコマンドで使用できます。
にはいくつかの一般的なユース ケース $PSItem
があります。
- コマンドレットの Process パラメーターの scriptblock 内
ForEach-Object
- コマンドレットの FilterScript パラメーター
Where-Object
の scriptblock - 組み込みメソッド ForEach と Where
- 遅延バインド scriptblock パラメーター
- ステートメントの条件付き
switch
値と関連するスクリプトブロック内 - 関数の
process
ブロック内 - 定義内
filter
- ValidateScript 属性の scriptblock
- 演算子の置換オペランド scriptblock 内
-replace
この記事の残りの部分には、これらのユース ケースに を使用 $PSItem
する例が含まれています。
ForEach-Object プロセス
ForEach-Object コマンドレットは、パイプライン内のオブジェクトを操作し、パイプライン内のすべてのオブジェクトに対して Process パラメーターのスクリプトブロックを 1 回実行するように設計されています。
Process パラメーターの scriptblock で を使用できますが、Begin または End パラメーターのスクリプトブロックでは使用$PSItem
できません。 Begin または End パラメーターの scriptblocks で参照$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 パラメーターの scriptblock で を使用$PSItem
できます。
1, 2, 3 | Where-Object -FilterScript { ($PSItem % 2) -eq 0 }
2
この例では、 FilterScript は、現在のオブジェクトが偶数であるかどうかを確認し、奇数の値をフィルター処理し、元のリストからのみ 2
返します。
ForEach メソッドと Where メソッド
配列の ForEach および Where 組み込みメソッドはどちらも、入力パラメーターとして scriptblock を受け取ります。 これらのスクリプトブロックで を $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 ステートメントの scriptblocks
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
を使用できますが、 begin
または end
ブロック定義では使用$PSItem
できません。 または end
ブロックで begin
を参照$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)\/"
}
]
フィルター定義
フィルターの定義のステートメント 一覧で を使用$PSItem
できます。
定義で をfilter
使用$PSItem
する場合、フィルターがパイプラインで呼び出される場合は値が現在のオブジェクトになります。それ以外の場合$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
は検証中の現在のオブジェクトの値です。 変数またはパラメーター値が配列の場合、scriptblock は、現在のオブジェクトとして を使用 $PSItem
して、配列内の各オブジェクトに対して 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 演算子を呼び出し、置換スクリプトブロックを定義するときに を使用$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 にキャストすることで、元の日付文字列を現在のカルチャの既定の形式に置き換えます。