带字符串数组的powershell函数开关参数

带字符串数组的powershell函数开关参数,powershell,Powershell,我正在努力理解下面函数的输出 function testApp { param( [string] $appName, [switch] $sw = $false, [string[]] $test, [string[]] $test2 ) Write-Host $appName - $sw - $test - $test2 } testApp-appName“testApp”-sw$true-测试“一”

我正在努力理解下面函数的输出

function testApp
{
    param(
        [string] $appName,
        [switch] $sw = $false,
        [string[]] $test,
        [string[]] $test2
    )

    Write-Host $appName - $sw - $test - $test2
}
  • testApp-appName“testApp”-sw$true-测试“一”、“二”-测试2“三”、“四”
  • 输出:TestApp-True-一两三四

  • testApp-appName“testApp”-sw$true-测试“一”、“二”
  • 输出:TestApp-True-一两-True

    第一个输出如预期的那样。但是我无法理解为什么第二个输出在我没有通过测试2数组时为“True”。有人能帮我理解这种行为的原因吗?谢谢。

    总结并补充以下人员对问题的有用意见:

    [switch]
    PowerShell中的参数(在其他shell中也称为标志): 参数意味着在调用中通过它们的存在来暗示
    $true
    $false
    :例如,传递
    -sw
    本身表示
    $true
    ,而忽略
    -sw
    表示
    $false

    • 为了传递编程确定的值,可以显式传递布尔值;e、 g.:
      -sw:$var

      • 注意开关名称后所需的
        ,它告诉PowerShell布尔值属于开关参数;没有它,PowerShell认为该值是一个位置参数,用于不同的参数(见下文)

      • 警告:命令解释
        -sw:$false
        与省略
        -sw
        不同;一个突出的例子是使用公共参数
        -Confirm:$false
        覆盖有效的
        $ConfirmPreference

        • 如果您需要在自己的代码中进行此区分,请使用
          $PSBoundParameters.ContainsKey('sw')-和-not$sw
          来检测
          -sw:$false
          案例
    • 不要为开关参数变量指定默认值:虽然技术上可行,约定是将默认值切换为
      $false
      (这是
      [switch]
      实例的默认值);也就是说,
      [switch]
      参数应该始终具有opt-in逻辑

    A
    [switch]
    参数变量在大多数上下文中的行为与布尔值类似:

    • 也就是说,例如,您可以说
      if($sw){…}

    • 如果需要显式访问包装的布尔值,请访问
      .IsPresent
      属性(请注意,属性名称有些混乱,因为在
      -sw:$false
      调用中,开关仍然存在,但其值(如
      .IsPresent
      中所反映的)是
      $false

      • 需要使用
        .IsPresent
        的一个示例是使用布尔值作为隐式数组索引,特别是为了模拟三元条件[1]:
        ('falseValue','trueValue')[$sw.IsPresent]
        ;如果没有
        .IsPresent
        ,有效的布尔值将不会被识别,也不会自动映射到索引
        0
        (来自
        $false
        )或
        1
        (来自
        $true

    最终,您的问题是您认为
    $true
    -sw
    的一个参数,而它变成了隐式绑定到
    -test2
    参数的位置参数

    [switch]
    参数永远不需要值,因此下一个参数将成为一个单独的位置参数-除非您在开关名称后面加上
    ,以明确指示该参数属于开关,如上所示。[2]

    在PowerShell中传递位置参数与命名参数: 术语说明:为了概念清晰,术语参数用于指传递给声明参数的值。这避免了在特定情况下使用参数来引用接收值和给定值的语言结构的模糊性

    • 命名参数传递(绑定)指显式地将目标参数名称放在参数之前(通常用空格分隔,但也可以用和/或
      )分隔);e、 例如,
      -AppName foo

      • 命名参数的传递顺序并不重要
    • 位置(未命名)参数传递指传递一个参数而不在其目标参数名称之前;e、 例如,
      foo

      • 传递是位置性的,因为其他未命名参数之间的相对位置(顺序)决定了隐含的目标参数
    • [switch]
      参数是例外,因为它们:

      • 通常仅按名称传递(
        -sw
        ),表示值
        $true
        ,如果传递了值,则需要
        将名称与值分开
      • 永远不支持位置绑定
    • 您可以将命名传递与位置传递相结合,在这种情况下,首先绑定命名参数,然后考虑(按顺序)绑定到尚未绑定的参数

    • 默认情况下,PowerShell函数是简单函数为了对位置绑定进行控制,必须使用
      [CmdletBinding()]
      和/或
      [Parameter()]
      属性(见下文),这会将简单函数转换为高级函数

      • 将简单功能变为高级功能具有更大的行为含义(大部分是有益的),详细信息请参见
    • 默认情况下,PowerShell函数接受任何参数的位置参数