powershell 参数如何绑定到管道中的第二个位置?

m1m5dgzv  于 2022-12-23  发布在  Shell
关注(0)|答案(1)|浏览(160)

我试图理解参数是如何绑定到管道中cmdlet的第二个位置的。
已尝试使用Select-String [1]进行尝试。它具有-Path,可接受位置1(第二个位置)处的管道输入。这些操作起作用:

sls "the-pattern" "the-file.txt"
"the-file.txt" | sls "the-pattern" -path {$_}

但这并不:

"the-file.txt" | sls "the-pattern"

在后一种情况下,我希望“the-file.txt”作为第二个参数绑定到sls

在Powershell中,第一个位置之后的参数绑定如何工作?

[1] https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/select-string?view=powershell-7.3#parameters

ezykj2lf

ezykj2lf1#

Get-Help提供了回答您问题的关键信息:

Get-Help Select-String -Parameter LiteralPath, Path, Pattern, InputObject |
    Select-Object Name, Position, PipelineInput, Aliases

我们可以看到以下几点:

name        position pipelineInput         aliases
----        -------- -------------         -------
LiteralPath named    True (ByPropertyName) PSPath, LP
Path        1        True (ByPropertyName) none
InputObject named    True (ByValue)        none
Pattern     0        False                 none

-LiteralPath-Path都是按属性名绑定的,而-InputObject是按值绑定的。
知道了这一点,我们可以在第一个例子中假设如下:

sls "the-pattern" "the-file.txt"
  • "the-pattern"在位置上结合到-Pattern上。
  • "the-file.txt"在位置上结合到-Path上。

在第二个示例中:

"the-file.txt" | sls "the-pattern" -path {$_}
  • "the-pattern"在位置上结合到-Pattern上。
  • "the-file.txt"使用延迟绑定脚本块通过名称绑定到-Path**。

在第三个例子中,它运行得很好,只是没有按照你预期的方式运行:

"the-file.txt" | sls "the-pattern"
  • "the-file.txt"通过来自管道的值绑定到-InputObject
  • "the-pattern"在位置上结合到-Pattern上。

您可以通过简单地尝试"the-file.txt" | sls "the-file"来了解这一点。
至于你没有尝试的东西,Trace-Command对理解参数是如何绑定的有很大帮助。这个特殊的例子一开始很难理解,因为Select-String总是从管道绑定-InputObject,无论如何(这是因为参数类型为PSObject)并且最有可能具有内部逻辑来确定何时应该将来自流水线的对象作为文件来对待并从其路径读取。
下面是一个例子,我的意思是使用一个临时文件。$tmp应该绑定到-LiteralPath,因为对象有.PSPath属性,但它被绑定到-InputObject

$tmp = New-TemporaryFile
$tmp = Get-Item $tmp.FullName
Trace-Command ParameterBinding { $tmp | sls .+  } -PSHost
    • 产出**
BIND NAMED cmd line args [Select-String]
BIND POSITIONAL cmd line args [Select-String]
    BIND arg [.+] to parameter [Pattern]        
        Binding collection parameter Pattern: argument type [String], parameter type [System.String[]], collection type Array, element type [System.String], no coerceElementType
        Creating array with element type [System.String] and 1 elements
        Argument type String is not IList, treating this as scalar
        Adding scalar element of type String to array position 0
        BIND arg [System.String[]] to param [Pattern] SUCCESSFUL
MANDATORY PARAMETER CHECK on cmdlet [Select-String]
CALLING BeginProcessing
BIND PIPELINE object to parameters: [Select-String]
    PIPELINE object TYPE = [null]
    RESTORING pipeline parameter's original values
    Parameter [InputObject] PIPELINE INPUT ValueFromPipeline NO COERCION
    BIND arg [] to parameter [InputObject]
        BIND arg [] to param [InputObject] SUCCESSFUL
MANDATORY PARAMETER CHECK on cmdlet [Select-String]
CALLING ProcessRecord
CALLING EndProcessing

For anyone wondering, here is the logic in the source code where it checks if the input object is a FileInfo instance: https://github.com/PowerShell/PowerShell/blob/master/src/Microsoft.PowerShell.Commands.Utility/commands/utility/MatchString.cs#L1502-L1509

相关问题