powershell 函数中未使用参数的默认值

3phpmpom  于 2023-01-13  发布在  Shell
关注(0)|答案(4)|浏览(219)

我有一个非常基本的PowerShell脚本:

Param(
    [string]$MyWord
)

function myfunc([string] $MyWord) {
    Write-Host "$MyWord"
}
myfunc @PSBoundParameters

我是这样执行的:

PS C:\> .\test.ps1 -MyWord 'hello'
hello

一切正常。但是如果没有指定-MyWord,我想设置一个默认值。我尝试了以下方法:

Param(
    [string]$MyWord='hi'
)

function myfunc([string] $MyWord) {
    Write-Host "$MyWord"
}
myfunc @PSBoundParameters

但是我的脚本输出是空的。当我没有描述我的参数时,它什么也不打印。(如果我指定了参数,它只显示'hello')。我还尝试了:

Param(
    [string]$MyWord
)

function myfunc([string] $MyWord) {
    [string]$MyWord='hi'
    Write-Host "$MyWord" 
}
myfunc @PSBoundParameters

但是输出总是“hi”而不是“hello”,即使我使用参数-MyWord 'hello'执行脚本也是如此
有人能解释一下我做错了什么吗?
当我不使用该函数时,它按预期工作:

Param(
    [string]$MyWord='hi'
)
Write-Host $MyWord

输出:

PS C:\> .\test.ps1 -MyWord 'hallo'
hallo

PS C:\> .\test.ps1
hi
zaqlnxep

zaqlnxep1#

顾名思义,自动变量**$PSBoundParameters只包含 bound 参数,其中bound 表示实际值由 * 调用者*提供。
因此,参数默认值不 * 符合 * 绑定
关联参数的条件,因此默认值为'hi'$MyWord * 不 * 成为$PSBoundParameters的一部分。

:当然,具有默认值的参数也应被视为绑定参数(它由它的 * 默认值 * 绑定,而不是由调用者提供的值绑定)。无论哪种方式,具有也包括默认值的自动变量将是方便的,以便能够简单而全面地传递参数。已向PowerShell存储库as GitHub issue #3285提交了建议。

变通方案

  • 下面的解决方案假设您希望通过*传递默认值,而不希望在函数myfunc中简单地复制默认值(如Ansgar Wiecher's helpful answer中所示),因为这会增加维护负担。
  • 关于函数 * 语法*:以下两种形式是 * 等价的 *(在本例中),尽管出于一致性和可读性,您可能更喜欢后者。[1]
  • function myfunc([string] $MyWord = 'hi') { ... }

*(...)内函数名 * 后的参数声明。

  • function myfunc { param([string] $MyWord = 'hi') ... }

param(...)块内的参数声明 * 在函数体内 *。
一个简单的修正是将默认值显式添加到$PSBoundParameters

Param(
     [string]$MyWord = 'hi'
)

function myfunc ([string] $MyWord){
    Write-Host "$MyWord" 
}

# Add the $MyWord default value to PSBoundParameters.
# If $MyWord was actually bound, this is effectively a no-op.
$PSBoundParameters.MyWord = $MyWord

myfunc @PSBoundParameters

为了**实现你想要的 * 一般性 *,**你必须使用反射(内省):

Param(
     [alias('foop')]
     [string]$MyWord = 'hi'
)

function myfunc ([string] $MyWord){
    Write-Host "$MyWord" 
}

# Add all unbound parameters that have default values.
$boundAndDefaultValueParams = $PSBoundParameters
foreach($paramName in $MyInvocation.MyCommand.Parameters.Keys) {
  if (-not $boundAndDefaultValueParams.ContainsKey($paramName)) {
    $val = Get-Variable $paramName -ValueOnly
    if ($null -ne $val) { $boundAndDefaultValueParams.Add($paramName, $val) }
  }
}

myfunc @boundAndDefaultValueParams

[1]如果需要使用具有非默认值的[CmdletBinding()]属性,以及在 * 脚本 *(.ps1)中使用param(...)表单,则param(...)表单是 * 必需的 *。请参见this answer

vsaztqbk

vsaztqbk2#

仅当实际向参数传递值时,参数才被绑定,这意味着参数的默认值不会显示在$PSBoundParameters中。如果要将脚本参数传递到函数中,则必须在函数参数集中复制脚本参数集:

Param(
    [string]$MyWord = 'hi'
)

function myfunc([string]$MyWord = 'hi') {
    Write-Host "$MyWord" 
}

myfunc @PSBoundParameters

但是,如果您以相同的方式定义两个参数集,那么维护这样的内容会更容易,所以我也将函数参数定义放在Param()块中:

Param(
    [string]$MyWord = 'hi'
)

function myfunc {
    Param(
        [string]$MyWord = 'hi'
    )

    Write-Host "$MyWord" 
}
eulz3vhy

eulz3vhy3#

如果要使用“Param”,请将其包含在函数中,如下所示:

function myfunc {

    Param(
        [string]$MyWord='hi'
    )

    Write-Host "$MyWord" 
}
h79rfbju

h79rfbju4#

很简单的方法是,

function myfunc([string]$MyWord = "hi") {
Write-Output $MyWord
}

相关问题