电源外壳"special"开关参数



我在下面有powershell函数

Function Test
{
Param
(               
[Parameter()]
[string]$Text = "default text"
)
Write-Host "Text : $($Text)"
}

我希望能够调用以下函数:

测试-文本:应在主机上显示默认文本

测试-文本"另一个文本">:应在主机上显示提供的文本

我的问题是powershell中不允许使用第一个语法。。

我有什么想法可以实现这个目标吗?我想要一种"switch"参数,它可以采用布尔值以外的值。

感谢

您遇到的问题是参数绑定。PowerShell正在看到[string] $Text,并且需要一个值。你可以这样做:

function Test {
param(
[switch]
$Text,
[Parameter(
DontShow = $true,
ValueFromRemainingArguments = $true
)]
[string]
$value
)
if ($Text.IsPresent -and [string]::IsNullOrWhiteSpace($value)) {
Write-Host 'Text : <default text here>'
}
elseif ($Text.IsPresent) {
Write-Host "Text : $value"
}
}

注意:这是一个棘手的解决方案,当参数没有传递时,您应该只有一个默认值。

tl;dr

  • PowerShell不支持带有可选值的参数。

  • 解决方法是可行的,但仅适用于单个参数。


Maximilian Burszley的有用答案为单个参数提供了解决方法,该方法通过catch-all参数收集所有通过ValueFromRemainingArguments参数属性在位置上传递的参数。

不过,从根本上讲,您所要求的是PowerShell中不支持

PowerShell不支持自7.2-起具有可选值的参数,但[switch]参数除外,后者仅限于[bool]的值

即:

  • 您用除[switch]之外的类型声明的任何参数都必然需要值(参数(。

  • 唯一的其他选项是不加区分地收集ValueFromRemainingArguments标记参数中任何未绑定的位置参数,但您将无法将这些参数与任何特定的其他绑定参数关联

换句话说:

  • 如果您碰巧只需要一个可选参数,ValueFromRemainingArguments可以为您工作(除了您应该手动处理错误接收多个值的情况(,如Maximilian Burszley的回答所示。

  • 如果您有两个或多个这样的参数,这种方法将变得不切实际:您必须知道参数是按哪个顺序传递的(PowerShell没有告诉您(,以便将剩余的位置参数与正确的参数相关联。


使用[switch]参数(以想象中的-Quiet开关为例(:

  • 如果您刚刚通过-Quiet,则默认值为$true
  • $false通常通过简单地根本不指定开关来指示(即省略-Quiet(

但是,可以通过在开关名称后面跟:,然后跟布尔值来显式地指定一个值

  • -Quiet:$true-Quiet相同

  • -Quiet:$false,典型地与省略-Quiet相同;不过,在极少数情况下,命令会区分省略的开关和具有显式$false值的开关;值得注意的是,公共-Confirm参数允许使用-Confirm:$false-而不是-Confirm-的省略来覆盖$ConfirmPreference偏好变量的值。

虽然:作为参数名称和参数之间的分隔符(与通常的空格字符相反(受所有参数的支持,但对于[switch]参数,它是必须,以便明确地表明后面是开关参数的参数(默认情况下,位置参数。


以上告诉我们,PowerShell已经具有语法,用于对可选参数参数的常规支持,因此在未来的某个时候它可以使用任何数据类型来支持它们,如GitHub问题#12104中所建议的。

我喜欢@Maximilian Burszley对String的回答(和他的名字!(,我对Ints:进行了调整

function Optional-SwitchValue {
[CmdletBinding()]
param (
[Switch]
$Bump,
[Int]
$BumpAmount
)
Begin {
# nifty pattern lifted from https://stackoverflow.com/questions/58838941/powershell-special-switch-parameter
# default Bump to 1
if ($Bump.IsPresent -and -not $BumpAmount) {
$BumpAmount = 1
}
}

Process {
if($Bump) {
#use $BumpAmount in some way
}
}
}

最新更新