是否有一个适用于if($?)的Powershell模式{ }?
PowerShell(核心)7.0引入了类似Bash的&&和||运算符,称为管道链操作符。它们不会被回溯到Windows PowerShell,因为后者通常不会看到新功能。
简而言之,不再需要使用以下代码:
do-cmd-one; if ($?) { do-cmd-two }
注意:截至PowerShell 7.1,更健壮的表达方式实际上是:
do-cmd-one; if ($LASTEXITCODE -eq 0) { do-cmd-two }
原因请参见此答案中的解释。
现在可以这样写:
do-cmd-one && do-cmd-two
&&(AND)和||(OR)隐式地根据每个命令的隐含成功状态进行操作,这反映在自动布尔变量$?中。
这在处理外部程序时可能更有用,它们的退出码明确地表示$?是$true(退出码为0)还是$false(任何非零退出码)。
相比之下,对于PowerShell命令(cmdlet),$?只反映命令是否作为整体失败(发生语句终止错误)或是否报告了至少一个非终止错误;后者并不一定表示总体失败。
然而,有计划允许PowerShell命令直接设置$?,作为明确的总体成功指示符。
还要注意,以下情况不适用于&&和||:
- PowerShell的Test-* cmdlet,因为它们通过输出布尔值而不是设置$?来表示测试结果;例如,Test-Path $somePath || Write-Warning "File missing"将无法正常工作。
- 布尔表达式,原因相同;例如,$files.Count -gt 0 || write-warning 'No files found'将无法正常工作。
有关背景信息,请参见此答案,并在GitHub问题#10917中进行讨论。
语法注意事项:截至撰写本文,以下代码不起作用:
do-cmd-one || exit 1 # !! 当前不起作用
而是被迫使用$(...)来包装exit / return / throw语句,即所谓的子表达式运算符:
do-cmd-one || $(exit 1) # 注意需要 $(...)
GitHub问题#10967讨论了这种笨拙要求的原因,这些原因根源于PowerShell语法的基本原理。
有没有一个PowerShell模式可以实现if($?) {}这样的功能?
问题的出现原因:
从给出的代码可以看出,作者想要在if语句中检查前一个命令的退出代码(exit code),如果退出代码为真($?为真),则执行第二个命令,否则退出脚本。然而,作者意识到if语句不能直接检查命令的退出代码。因此,作者尝试了一些其他方法来实现这个功能,但都不够简洁或者存在其他问题。
解决方法:
在给出的代码中,作者使用了一种不太优雅的解决方法,即在if语句中调用第一个命令,并通过检查命令的输出来判断命令是否成功执行。如果命令没有输出,则认为命令执行失败;如果命令有输出,则认为命令执行成功。这种方法可以通过隐藏错误消息来实现。然而,这种方法存在一些问题,如可能会产生误报,因为第一个命令可能会产生输出,同时返回$false。另外,这种方法也会丢弃命令的标准输出/成功流输出。
除了这种方法之外,还可以使用PowerShell中提供的其他功能来实现类似的功能。例如,可以使用Test-Connection命令的-Quiet选项来返回一个布尔值,来判断命令是否成功执行。这种方法比之前的方法更简洁,而且不会产生误报。然而,这种方法也有一些局限性,因为它只适用于特定的命令,并且需要了解命令的具体用法。
从以上讨论可以看出,PowerShell中没有直接支持if($?) {}这样的语法来检查命令的退出代码。然而,可以通过一些技巧和使用特定命令的选项来实现类似的功能。需要根据具体的需求和命令来选择合适的方法来判断命令是否成功执行。