about_PSItem

簡短描述

包含管線物件中目前對象的自動變數。

詳細描述

PowerShell 包含 $PSItem 變數及其別名, $_做為 腳本區塊中處理目前對象的自動變數 ,例如在管線中。 本文 $PSItem 會在範例中使用 ,但 $PSItem 可以在每個範例中取代為 $_

您可以在命令中使用這個變數,在管線中的每個物件上執行動作。

有一些常見的使用案例 $PSItem

  • 在 Cmdlet 之 Process 參數的 ForEach-Objectscriptblock
  • Cmdlet 之 FilterScript 參數Where-Objectscriptblock 中
  • In the intrinsic methods ForEach and Where
  • 具有延遲系結腳本區塊參數
  • switch在語句的條件值和相關聯的 scriptblock 中
  • 函式區塊 process 中的
  • filter定義中的
  • 在 ValidateScript 屬性的 scriptblock 中
  • 在運算子的 -replace 替代操作數 scriptblock 中

本文的其餘部分包含使用這些使用案例的 $PSItem 範例。

ForEach-Object Process

ForEach-Object Cmdlet 的設計目的是在管線中的物件上操作,針對管線中的每個物件執行 Process 參數的 scriptblock 一次。

您可以在 Process 參數的 scriptblock 中使用$PSItem,但無法在 BeginEnd 參數 scriptblocks 中使用 如果您在 Begin 或 End 參數 scriptblocks 中參考 ,則值是因為$null這些文稿區塊不會在管線中的每個物件上運作。$PSItem

$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 Cmdlet 是設計來篩選管線中的物件。

您可以在 $PSItem FilterScript 參數的 scriptblock 中使用 ,該區塊會針對管線中的每個輸入物件執行一次。

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

在此範例中 ,FilterScript 會檢查目前的物件是否為偶數,並篩選掉任何奇數值,並且只會 2 從原始清單傳回。

ForEach 和 Where 方法

陣列的 ForEachWhere 內建方法都會採用 scriptblock 作為輸入參數。 您可以使用 $PSItem 這些文稿區塊中的 來存取目前的物件。

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

在此範例中,ForEach 方法的 scriptblock 會將目前的 對象大寫。 然後 Where 方法的 scriptblock 只會B傳回 。

延遲系結腳本區塊參數

延遲系結腳本區塊 可讓您在執行之前,先 $PSItem 定義管線 Cmdlet 的參數。

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

在此範例中,語句條件腳本區塊會檢查目前的物件是否偶數。 如果是偶數,相關聯的動作腳本區塊會輸出訊息,指出目前的物件為偶數。

條件的 default 動作腳本區塊會輸出訊息,指出目前物件為奇數。

函式進程區塊

當您定義函式時,可以在$PSItem區塊定義中使用process,但無法在 或 end 區塊定義中使用begin。 如果您在或 end 區塊中begin參考 $PSItem ,則值是因為$null這些區塊不會在管線中的每個物件上運作。

當您 $PSItem 在區塊定義中使用 process 時,如果管線中呼叫函式,則值為值是目前的物件,否則 $null為 。

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

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

提示

雖然您可以在$PSItem進階函式中使用,但幾乎沒有理由這麼做。 如果您想要從管線接收輸入,最好是使用Parameter屬性的ValueFromPipeline*其中一個自變數來定義參數。

針對進階函式使用Parameter屬性和 Cmdlet 系結,可讓實作比處理目前物件更明確且可預測,以取得所需的值。

在進階函式中,有一個良好的用法 $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是正在驗證之目前物件的值。 當變數或參數值是陣列時,會針對陣列中的每個物件呼叫 scriptblock 一次,並使用 $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 屬性的 scriptblock 會針對傳遞給 Number 參數的每個值執行一次,如果沒有任何值甚至沒有傳回錯誤, 就會傳回錯誤。

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

在此範例中,替代 scriptblock 會將值 轉換成 datetime,以目前文化特性的預設格式取代原始日期字串。

另請參閱