【问题标题】:Powershell: How to run an external command and checks its success in a single line?Powershell:如何运行外部命令并在一行中检查其是否成功?
【发布时间】:2019-11-18 15:24:53
【问题描述】:

在 bash 中,我可以这样做:

if this_command >/dev/null 2>&1; then
  ANSWER="this_command"
elif that_command >/dev/null 2>&1; then
  ANSWER="that_command"
else
  ANSWER="neither command"
fi

但在 Powershell 中,我必须这样做:

this_command >/dev/null 2>&1
if ($?) {
  ANSWER="this_command"
} else { 
  that_command >/dev/null 2>&1
  if ($?) {
    ANSWER="that_command"
  } else {
    ANSWER="neither command"
  }
}

或与($LASTEXITCODE -eq 0) 类似的东西。如何使 Powershell 看起来像 bash?我不是 Powershell 专家,但我不敢相信它没有提供某种方法来运行命令并以可以在 if-elseif-else 语句中使用的方式在单个语句中检查其返回代码。对于必须以这种方式测试的每个外部命令,该语句将越来越难以阅读。

【问题讨论】:

    标签: powershell if-statement


    【解决方案1】:

    对于 PowerShell cmdlet,您可以执行与 bash 中完全相同的操作。您甚至不需要在每个分支中进行单独的分配。只需输出您要分配的内容,并将整个条件的输出收集到一个变量中。

    $ANSWER = if (Do-Something >$null 2>&1) {
        'this_command'
    } elseif (Do-Other >$null 2>&1) {
        'that_command'
    } else {
        'neither command'
    }
    

    对于外部命令,它略有不同,因为 PowerShell 会评估命令输出,而不是退出代码/状态(输出为空 evaluating to "false")。但是您可以在子表达式中运行命令并输出状态以获得所需的结果。

    $ANSWER = if ($(this_command >$null 2>&1; $?)) {
        'this_command'
    } elseif ($(that_command >$null 2>&1; $?)) {
        'that_command'
    } else {
        'neither command'
    }
    

    请注意,您必须使用子表达式 ($(...)),而不是分组表达式 ((...)),因为您实际上需要连续运行 2 个命令(运行外部命令,然后输出状态),后者不支持。

    【讨论】:

      【解决方案2】:

      你不能像在bash 中那样内联,但是你可以在一行中用分号分隔两个语句 ;

      MyProgram.exe -param1 -param2 -etc *>$null; if( $LASTEXITCODE -eq 0 ) {
        # Success code here
      } else {
        # Fail code here
      }
      

      此外,您不能将 $? 与命令一起使用,只能使用 Powershell cmdlet,这就是我们检查 $LASTEXITCODE -eq 0 而不是使用 $? 的原因。


      请注意,您CAN 内联评估 cmdlet,而不是外部命令。例如:

      if( Test-Connection stackoverflow.com ){
        "success"
      } else {
        "fail"
      }
      

      【讨论】:

        【解决方案3】:

        另一种方法是让它输出一个空字符串,如果它是假的:

        if (echo hi | findstr there) { 'yes' }
        if (echo hi | findstr hi) { 'yes' }
        yes
        

        【讨论】:

          【解决方案4】:

          PowerShell 的本机错误处理与外部程序执行的基于退出代码的错误信号完全不同,不幸的是,PowerShell 中外部程序的错误处理很麻烦,需要显式检查自动 $?$LASTEXITCODE 变量

          PowerShell [核心]

          • v7 中引入了对 Bash 风格的 &&|| 管道链运算符 的支持 - 请参阅 @987654321 @。

          • 但这将也允许在if语句中使用外部程序调用,因为PowerShell将继续对命令的输出进行操作,而不是他们隐含的成功状态/退出代码;更多信息请参见this answer

          解决方案


          PowerShell [核心] 7.0+

          $ANSWER = this_command *>$null && "this_command" || 
                    (that_command *>$null && "that_command" || "neither command")
          

          注意:

          • 如果this_commandthat_command存在(找不到),则会发生语句终止错误,即语句作为一个整体失败。

          • 注意需要将第二条链包含在(...) 中,这样&& "that_command"this_command 成功时也不会启动。

          • *>$null 用于通过一次重定向方便地使 所有 流静音。

          • 与基于if 的解决方案不同,此技术通过传递(非抑制)外部程序的输出。


          Windows PowerShell 和 PowerShell Core 6.x:

          • 如果外部程序调用没有产生输出,或者您想抑制它们的输出,如您的问题所示:

          • 如果您确实想要外部程序的输出

          辅助。 dummy do 循环允许相当“低噪音”的解决方案:

          $ANSWER = do {
          
            this_command   # Note: No output suppression
            if ($?) { "this_command"; break }
          
            that_command   # Note: No output suppression
            if ($?) { "that_command"; break }
          
            "neither command"
          
          } while ($false)
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-09-21
            • 2021-10-22
            • 1970-01-01
            • 2015-07-12
            • 1970-01-01
            • 2012-08-06
            • 1970-01-01
            相关资源
            最近更新 更多