【问题标题】:PowerShell's parsing modes: argument (command) mode vs. expression modePowerShell的解析模式:参数(命令)模式与表达式模式
【发布时间】:2018-07-24 09:02:06
【问题描述】:

谁能解释为什么当从 powershell 函数返回 $false 时,您无法使用比较运算符来确定函数是否返回了 $false,但是当您返回 $true 时,比较结果为 $true?

function boolean {
    return $false
}

boolean -eq $false

function boolean {
    return $true
}

boolean -eq $true

>>>False
>>>True

您可以通过将函数调用设置为变量来解决此问题,但我想知道是否有人可以解释这里发生了什么?

function boolean {
    return $false
}

$bool = boolean 
$bool -eq $false

function boolean {
    return $true
}

$bool = boolean
$bool -eq $true

>>>True
>>>True

【问题讨论】:

    标签: powershell parsing syntax


    【解决方案1】:

    PowerShell 有两种基本解析模式

    • argument模式,其工作方式类似于传统的shell

      • 在参数模式下,第一个标记被解释为 命令名(例如 cmdlet 名称、函数名或脚本或外部可执行文件的文件名),后跟 空格分隔的列表 参数
    • 表达式模式,类似于传统的编程语言

    运行Get-help about_Parsing 提供了这些模式的介绍;简而言之,第一个标记决定了应用哪种模式。
    另请注意,给定语句可能由在任一模式下解析的部分组成。


    boolean -eq $falseargument 模式下解析,因为它的第一个标记看起来像 命令名(标识符,可以是程序名称、cmdlet 名称、函数名称或别名)。

    因此,-eq$false 被解释为参数(参数值)以传递给函数boolean

    由于您的boolean 函数的定义方式不强制将值仅传递给声明的参数,因此参数实际上被忽略,结果该语句是函数输出的任何内容($false$true)。

    正如Mike Shepard's answer 中所展示的,您可以使函数强制仅使用 声明的 参数(包括 none),并带有装饰有 param() 的块[CmdletBinding()] 属性(使函数成为advanced function),如果您无意中将参数传递给无参数的boolean 函数,这至少会导致错误。


    您可以通过将函数调用设置为变量来解决此问题

    $bool = boolean   # execute function and capture result in variable
    $bool -eq $false  # use variable in the comparison 
    

    之所以有效是因为-eq 语句$ 开头——在这种情况下是一个变量引用——这会导致 PowerShell 在 表达式 模式下进行解析,其中-eq 被识别为操作员$false 被识别为其RHS。

    但是,不需要这个中间步骤:

    强制将一段代码解释为表达式,请将其括在(...) 中,grouping operator

    (boolean) -eq $false # Calls function 'boolean' and uses result as LHS of -eq
    

    (...) 强制一个新的解析上下文(它本身在参数或表达式模式下解析,同样取决于第一个标记)并且 将结果视为 表达式。然后允许将其用作更大表达式的一部分,例如-eq 运算符的操作数,或作为命令参数

    【讨论】:

      【解决方案2】:

      PowerShell 将 -eq 视为传递给“布尔”函数的参数名称。

      要看到这一点,您可以将函数调用放在括号中:

      function boolean {
          return $false
      }
      
      (boolean) -eq $false
      
      function boolean {
          return $true
      }
      
      (boolean) -eq $true
      

      或者,您可以将其设置为高级功能,这样您就会收到缺少参数 (-eq) 的错误:

      function boolean {
      [CmdletBinding()]
      Param()
          return $false
      }
      
      boolean -eq $false
      
      function boolean {
      [CmdletBinding()]
      Param()
          return $true
      }
      
      boolean -eq $true
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-06-27
        • 2018-10-29
        • 2011-02-20
        • 2013-12-31
        • 2012-10-23
        • 2010-10-16
        • 1970-01-01
        • 2013-08-04
        相关资源
        最近更新 更多