Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PowerShell函数参数:第一个参数可以是可选的吗?_Powershell_Parameters - Fatal编程技术网

PowerShell函数参数:第一个参数可以是可选的吗?

PowerShell函数参数:第一个参数可以是可选的吗?,powershell,parameters,Powershell,Parameters,我在PowerShell中有一个高级函数,大致如下所示: function Foo { [CmdletBinding] param ( [int] $a = 42, [int] $b ) } function ff() { param($a, $b) $go = { param($a, $b) "a: $a" "b: $b" } if (!$PSBoundPa

我在PowerShell中有一个高级函数,大致如下所示:

function Foo {
    [CmdletBinding]
    param (
        [int] $a = 42,
        [int] $b
    )
}
function ff() {
    param($a, $b)
    $go = {
        param($a, $b)
        "a: $a"
        "b: $b"
    }
    if (!$PSBoundParameters.ContainsKey('b')) { 
        &$go -b $a 
    } 
    else {
        &$go @PSBoundParameters
    }
}
其思想是,它可以使用两个、一个或没有参数运行。但是,第一个变为可选的参数是第一个。因此,以下场景可以运行该功能:

Foo a b    # the normal case, both a and b are defined
Foo b      # a is omitted
Foo        # both a and b are omitted
但是,通常情况下,PowerShell会尝试将单个参数放入。所以我考虑显式地指定参数位置,其中a的位置为0,b的位置为1。然而,为了只允许指定b,我尝试将a放入参数集中。但是b需要一个不同的位置,这取决于当前使用的参数集


有没有办法妥善解决这个问题?我希望保留参数名(实际上不是a和b),因此使用
$args
可能是最后的选择。我可能可以定义两个参数集,一个带有两个强制参数,另一个带有一个可选参数,但我想在这种情况下,参数名称必须不同,对吗?

关于如何正确解决这个问题的想法?不。我已经说过,如果位置0处的参数是管道绑定的,则任何其他参数的“位置”向下滑动1,以便您可以继续提供位置参数,而不必求助于所有命名参数。团队认为这对人们来说太令人困惑了——让参数改变位置。此行为是将管道绑定参数放在位置参数末尾的一个很好的理由。:-)

顺便说一句,对于高级功能,$args不是一个选项。有点像$\它不适用。使用剩余参数中的值,例如:

    [Parameter(ValueFromRemainingArguments=$true)]
    $rest

恐怕你不能这样做。你能得到的最接近的是必须命名第一个参数。可选的未命名位置参数必须是集合中的最后一个

function test-optional {
    [cmdletbinding(defaultparametersetname="SingleOrNone")]
    param(
        [parameter(
            parametersetname="Both",
            mandatory=$true,
            position=1)]      
        [int]$A,

        [parameter(
            parametersetname="Both",
            mandatory=$false,
            position=2)]
        [parameter(
            parametersetname="SingleOrNone",
            mandatory=$false,
            position=1)]
        [int]$B   
    )

    end {
        "parameterset: {0}; a: $a; b: $b" -f $pscmdlet.parametersetname, $a, $b
    }
}

test-optional 1 # ok
test-optional 3 4 # fail
test-optional -a 3 4 # ok
test-optional -a 1 # ok
test-optional -b 1 # ok
test-optional -a 1 -b 2 # ok
test-optional # ok

您可以使用动态参数(记录在“关于函数\u高级\u参数”中)实现这一点,这可能是“正确”的解决方案。但是,根据你论点的复杂性,你可以通过两种方式达到同样的效果

您可以使用正确的参数排列递归调用函数:

    function ff($a, $b) { 
        if (!$PSBoundParameters.ContainsKey('b')) {
            ff -b $a; return
        }

        # main logic
        "a: $a"
        "b: $b" 
    }
这导致:

PS C:\Users\Droj> ff one two
a: one
b: two
PS C:\Users\Droj> ff one
a:
b: one
PS C:\Users\Droj> ff
a:
b:
但这不允许您为参数定义不同的类型或验证。因此,如果需要,另一个选项是将主逻辑包装在脚本块中,并根据传入的内容传入正确的参数。大概是这样的:

function Foo {
    [CmdletBinding]
    param (
        [int] $a = 42,
        [int] $b
    )
}
function ff() {
    param($a, $b)
    $go = {
        param($a, $b)
        "a: $a"
        "b: $b"
    }
    if (!$PSBoundParameters.ContainsKey('b')) { 
        &$go -b $a 
    } 
    else {
        &$go @PSBoundParameters
    }
}
。。。结果是相同的输出


希望有帮助

尝试了一段时间通过DYNAMICPARAM找到解决方案,但a)我不确定它是否有效,b)代码看起来很难看,解析$args的效果要好得多。我不知道有哪种带有可选参数的编程语言允许第一个参数是可选的;可选参数(或者等价地,带有默认值的参数)必须跟在必需的参数后面。嘿,Keith,我想我们在一分钟之内就发布了这些参数。伟大的人都会拖延!好的,我不认为我迫切需要它成为一个高级功能。在像
函数foo{…}
这样简单的东西中,我可以同时使用
$args
$input
,对吗?是的,如果您避免创建允许$args和$input工作的“高级”函数。尽管使用
ValueFromRemainingArguments
ValueFromPipeline
可以很容易地获得这两个功能($args和$input),然后您可以从函数文档注释中获益。我只是说…:-)