PowerShell函数参数:第一个参数可以是可选的吗?
我在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
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),然后您可以从函数文档注释中获益。我只是说…:-)