为什么`if(Test-Path ...)`实际上有效?

Bor*_*ard 7 syntax powershell

在PowerShell中,语法if如下:

if (<test1>)
    {<statement list 1>}
[elseif (<test2>)
    {<statement list 2>}]
[else
    {<statement list 3>}]
Run Code Online (Sandbox Code Playgroud)

另一种语法规则是,对于子表达式,您需要使用如下括号:

 write-output (get-date)
Run Code Online (Sandbox Code Playgroud)

因此,结合这两个规则,我希望某些路径的测试需要用两组括号写成,如下所示:

if ((Test-Path ...)) {
    # do something
}
Run Code Online (Sandbox Code Playgroud)

但是,这也有效:

if (Test-Path ...) {
    # do something
}
Run Code Online (Sandbox Code Playgroud)

而且为了完整起见,这不起作用:

if (!Test-Path ...) {
    # do something
}
Run Code Online (Sandbox Code Playgroud)

(这里,您需要像往常一样将子表达式包装在括号中).

任何人都可以解释这里适用的语法规则,以及我如何只使用一个括号使用IF测试?它是一些PowerShell魔法还是我误解了基本的语法规则?

Emp*_*LII 4

参考附录 C: Bruce Payette 的Windows PowerShell 实际操作中的PowerShell 语法中的 C.2.2 ,我们有:

<ifStatementRule> =
  'if' '(' <pipelineRule> ')' <statementBlockRule>
  [ 'elseif' '(' <pipelineRule> ')' <statementBlockRule> ]*
  [ 'else' <statementBlockRule> ]{0|1}
Run Code Online (Sandbox Code Playgroud)

这表明()标记作为用于识别语句的文字语法的一部分if,并且文档<test>中的about_If指的是将解析为布尔值的管道。

根据管道规则,我们发现:

  • Test-Path ...解析为<cmdletCall>a <name> <parameterArgumentToken>,
  • !Test-Path ...导致<expressionRule>of <UnaryOperatorToken> <propertyOrArrayReferenceRule>,当 cmdlet 调用无法匹配简单属性或数组规则时,该操作会失败,而
  • !(Test-Path ...)能够将带括号的 cmdlet 调用作为子表达式进行匹配。

编辑:另请参阅PowerShell 2.0 语言规范(感谢Roman 对另一个问题的回答)。