【问题标题】:Can I suppress parameter aliases?我可以禁止参数别名吗?
【发布时间】:2014-02-12 23:58:42
【问题描述】:

鉴于此函数和调用:

function Foo($bar) { 
    Write-Host "bar=$bar, other args = $args"
}

Foo -b baz -quux quuux

Powershell 会将-b 参数视为$bar 参数的别名并打印

bar=baz, other args = -quux quuux

我不希望它这样做!我的函数需要同时使用命名参数和任意附加参数;如果这些任意参数之一是-b,我不希望它分配给$bar。也就是说,我希望它打印出来:

bar=, other args = -b baz -quux quuux

我可以抑制 powershell 所做的默认参数别名吗?

我正在使用 powershell 2.0

【问题讨论】:

    标签: powershell powershell-2.0


    【解决方案1】:

    AFAIK,你不能同时拥有它。您可以使用展示您在此处看到的行为的“基本”函数,也可以使用带有命名参数的高级函数,该函数将严格验证参数名称。

    “任意参数”变得非常非常难看,恕我直言,应该避免出于多种原因(其中一些涉及代码安全 - 你最终会执行未知的任意代码吗?)。

    Foo 设为高级函数,并将您的“任意”参数设为Objects 的集合,这是可选的。

    function Foo { 
    [cmdletBinding()]
    param (
        [Parameter(Mandatory=$True)]
        [string]$bar,
        [Parameter(Mandatory=$False)]
        [object[]]$args
    )
        Write-Output "bar=$bar";
        # Test for $args here and process each item in it
    
    }
    

    【讨论】:

    • 关于“您可以使用带有命名参数的高级函数,该函数将严格验证参数名称”-您的意思是说只接受确切的名称吗?如果是这样,怎么做?在您的示例上运行Foo -b abc 会打印bar=abc,所以我没有看到参数名称已经“严格”验证。 (PS 2.0)
    • 这真的很奇怪,我以为我的第一次运行肯定拒绝了-b,但我已经关闭了窗口,现在无法重现它。
    • 验证非任意参数/参数要容易得多,因为您在设计函数时就知道您的输入应该是什么样子。通过 PowerShell 的高级函数提供的内置验证,您可以设计验证比在函数体本身中编写额外的逻辑要容易得多。这与原始问题非常偏离主题。
    • 是的,我要删除我的 cmets。
    【解决方案2】:

    您可以通过引用来阻止解析器将 -b 解释为参数别名:

    function Foo($bar) { 
        Write-Host "bar=$bar, other args = $args"
    }
    
    Foo '-b' baz -quux quuux
    
    bar=-b, other args = baz -quux quuux
    

    【讨论】:

    【解决方案3】:

    PowerShell 无法禁用对参数明确前缀匹配的支持。

    虽然有各种权衡,但仍有一些选择。

    选项 1 - 自己解析参数:

    function foo {
        param()
    
        # $args has all of the parameters and arguments
    }
    

    这对你来说比较难写,但解决了你希望解决的问题,因为你将完全拥有参数/参数绑定。

    另一个缺点是参数没有制表符完成,至少在 TabExpansion 或 TabExpansion2 中没有一些额外的相应帮助(例如,使用 TabExpansion++ 或 PowerTab 之类的模块)。

    请注意,在此示例中,即使您有一个“来自剩余参数的值”的参数,您也不希望绑定 cmdlet,因为 cmdlet 绑定将添加公共参数,并且如果使用明确的前缀,这些参数将被绑定。

    选项 2 - 要求调用者做一些不同的事情

    有几个 cmdlet 存在类似问题,例如调用命令或获取命令。两者都接受一系列参数。用户必须引用参数:

    icm { param($a,$b) $b } -ArgumentList '-b','hello'
    

    这些 cmdlet 使用 -ArgumentList 是因为它们确实必须接受可能与 cmdlet 的参数冲突的任意参数。

    如果您的问题受到更多限制,可能还有另一种选择,但它需要一些不常用的语法,并且某些参数仍然存在问题。一个例子:

    function foo
    {
        param([Parameter(ValueFromRemainingArguments=$true)]$ArgumentList)
        $ArgumentList
    }
    
    foo -- -A 1 -Ar 2 -Arg 3
    

    特殊标记“--”告诉 PowerShell 后面的所有内容都是一个参数。这样,看起来像参数的参数被视为参数。

    如果调用者忘记了“--”,这种方法可能会令人困惑。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-15
      • 1970-01-01
      • 2015-09-20
      • 2011-03-24
      • 2018-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多