簡體   English   中英

電源外殼。 管道命令和使用 Foreach-Object 之間的區別

[英]Powershell. Difference between piping commands and using Foreach-Object

對不起,如果這個問題已經得到回答,我可以找到類似的問題,但不是我需要問的確切問題。

我們舉兩個例子:

 1. Get-Process -name msedge,putty | Stop-Process
 2. Get-Process -name msedge,putty | Foreach-Object {Stop-Process $_}

兩者都在做同樣的操作。 每種方法使用的方法是什么? 在第一個示例只是為了代碼可讀性/美學而省略Foreach-Object構造的意義上,它們是否相同?

第一個示例要求 Cmdlet 支持通過管道綁定相關參數。 在您的情況下, Stop-Process會將 Process 對象從管道綁定到它的-InputObject參數。

您可以使用get-help stop-process -Parameter *並查看哪些參數具有“接受管道輸入?” 設置為真。

如果 Cmdlet 不支持相關參數值的綁定,您可以將ForEach-Object包裹在它周圍,就像您在第二個示例中所做的那樣。 通過這種方式,您可以使用自動變量$_將當前管道對象(或您從中派生的信息)“手動”綁定到相應的參數。

如果 Cmdlet 支持綁定管道中的參數值,您應該使用什么方法? 不幸的是,這取決於。 可以編寫行為不同的 Cmdlet,具體取決於參數值的綁定方式。 讓我來說明這一點:

function Test-BindingFoo {
    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline)]
        [string[]]
        $InputParameter
    )
    
    begin {
        Write-Host "[BEGIN]"
    }
    
    process {
        foreach ($value in $InputParameter) {
            Write-Host "The current value is: $value"
        }
    }
    
    end {
        Write-Host "[END]"
    }
}

如果您使用管道綁定執行此 Cmdlet,則該函數的 Begin 塊只執行一次:

❯ "foo1", "foo2" | Test-BindingFoo
[BEGIN]
The current value is: foo1
The current value is: foo2
[END]

如果您使用ForEach-Object ,則每次對象通過管道時都會執行 Begin 塊:

❯ "foo1", "foo2" | ForEach-Object { Test-BindingFoo $_ }
[BEGIN]
The current value is: foo1
[END]
[BEGIN]
The current value is: foo2
[END]

在實施良好的 Cmdlet 中,這里的差異應該無關緊要。 但是我發現當以我們在此處討論的方式傳入參數時,了解 Cmdlet 內部發生的情況很有用。

您也可以這樣做,並在進程對象(操作語句)上使用 kill 方法:

Get-Process msedge,putty | Foreach-Object kill
# or
Get-Process msedge,putty | Foreach-Object -membername kill

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM