【问题标题】:Passing function arguments by position: Do explicit values get used before pipeline input?按位置传递函数参数:在管道输入之前是否使用显式值?
【发布时间】:2015-04-21 13:32:16
【问题描述】:

我正在尝试创建一个可以按位置接收多个参数的函数,包括管道输入。

这是一个简单的测试函数:

function TestMultiplePositionalParameters
{
    param
    (  
        [Parameter(
            Position=0, 
            Mandatory=$true)
        ]
        [String]$FirstParam,

        [Parameter(
            Position=1, 
            Mandatory=$true, 
            ValueFromPipeline=$true)
        ]
        [String]$SecondParam
    ) 

    begin
    {
        Write-Host '================================='
    }

    process
    {
        Write-Host '$FirstParam:' $FirstParam
        Write-Host '$SecondParam:' $SecondParam
        Write-Host ''        
    }
}

当我调用它时,它工作正常:

"Input1","Input2" | TestMultiplePositionalParameters 'ExplicitArgument'

结果:

=================================
$FirstParam: ExplicitArgument
$SecondParam: Input1

$FirstParam: ExplicitArgument
$SecondParam: Input2

但是,如果我更改从管道中获取值的参数:

function TestMultiplePositionalParameters
{
    param
    (  
        [Parameter(
            Position=0, 
            Mandatory=$true, 
            ValueFromPipeline=$true)
        ]
        [String]$FirstParam,

        [Parameter(
            Position=1, 
            Mandatory=$true)
        ]
        [String]$SecondParam
    ) 

    # etc...

}

再次调用它:

"Input1","Input2" | TestMultiplePositionalParameters 'ExplicitArgument'

这次我报错了:

TestMultiplePositionalParameters : The input object cannot be bound to any parameters 
for the command either because the command does not take pipeline input or the input 
and its properties do not match any of the parameters that take pipeline input.
At C:\...\DEMO_Function_Pipeline_MultiPositionalParams.ps1:77 char:21
+ "Input1","Input2" | TestMultiplePositionalParameters 'ExplicitArgument'
+                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (Input1:String) 
   [TestMultiplePositionalParameters ], ParameterBindingException
    + FullyQualifiedErrorId : InputObjectNotBound,TestMultiplePositionalParameters

我的问题是:为什么函数的第二个版本将显式参数“ExplicitArgument”传递给第一个参数?我原以为只有第一个参数可以接受管道输入,该函数应该将管道输入传递给第一个参数,并将显式参数传递给第二个参数。

【问题讨论】:

  • 做你所期望的需要命令启动,检查输入,然后绑定参数(我认为)。这似乎是一种奇怪的方式来发挥作用。
  • 当函数接受管道输入时,这不是实际发生的情况吗?在我的问题中,我忽略了我得到两个错误的事实,一个针对通过管道传递的每个值("Input1""Input2")。在我看来,该函数运行了开始块,然后返回并从管道中读取第一个值并尝试将其绑定到参数并进行处理(如果它没有抛出错误,如上面的第二个示例所示),然后它从管道中读取第二个值并对其进行绑定和处理。
  • 是的,它处理管道输入绑定命令行参数(并可能运行开始)。您建议的行为与此完全相反。它需要分配管道输入(在开始之前和命令行参数分配之前)。

标签: powershell pipeline powershell-4.0


【解决方案1】:

为什么函数的第二个版本传递显式参数 'ExplicitArgument' 到第一个参数?

因为$FirstParam 被标记为位于“0”位置,并且传递给 cmdlet 的第一个参数是“ExplicitArgument”。从本质上讲,在 PowerShell 寻找将接受管道输入的参数时,'ExplicitArgument' 到 $FirstParam 的绑定已经发生。

要获得预期的行为,您必须执行以下操作:

"Input1","Input2" | TestMultiplePositionalParameters -SecondParam 'ExplicitArgument'

这样做的原因是您可以有多个参数从管道中接受其值。如果您有以下情况,您希望在第二个示例中发生什么?

param
(  
    [Parameter(
        Position=0, 
        Mandatory=$true, 
        ValueFromPipeline=$true)
    ]
    [String]$FirstParam,

    [Parameter(
        Position=1, 
        Mandatory=$true,
        ValueFromPipeline=$true)
    ]
    [String]$SecondParam
) 

必须有一个优先级,即命名参数和位置参数的优先级高于管道参数。

【讨论】:

  • 对表明此绑定顺序的文档的引用将是一个很好的补充(如果有的话)。
  • @EtanReisner 我查看了about_Functions_Advanced_Parameters,并没有明确表示Position 优先于ValueFromPipeline。因此,我们必须从经验中推断出来。
  • 确实如此。我也没有看到任何表明这一点的东西(或我看过的其他几个地方)。如果存在的话,那就太好了(即使我认为这是自然顺序,并且建议的替代方案会让我非常感到惊讶)。
  • @Swoogan:非常明确的答案,谢谢。我也找不到任何关于函数参数绑定顺序的文档。
猜你喜欢
  • 1970-01-01
  • 2014-04-13
  • 2017-10-08
  • 2012-12-02
  • 2019-01-04
  • 1970-01-01
  • 1970-01-01
  • 2019-04-16
  • 2012-10-03
相关资源
最近更新 更多