53

在 Bash 中,我可以轻松地做类似的事情

command1 && command2 || command3

这意味着运行command1,如果command1成功运行command2,如果command1运行command3失败。

PowerShell 中的等价物是什么?

4

4 回答 4

49

更新终于来到了 PowerShell (Core) &&||v7;看到这个答案


在第一次提出这个问题多年后,让我总结一下 PowerShell v5.1 的情况

  • Bash 的 /cmd&&控制||运算符没有 PowerShell 等效项,并且由于您无法在 PowerShell 中定义自定义运算符,因此没有好的解决方法

    • 使用单独的命令(在单独的行或用 分隔;),并通过自动变量显式测试每个命令的成功状态$?,例如:
      command1 -arg1 -arg2; if ($?) { command2 -arg1 } # equivalent of &&
      command1 -arg1 -arg2; if (-not $?) { command2 -arg1 } # equivalent of ||

    • 请参阅下文,了解为什么 PowerShell-and-or通常不是解决方案。

  • 不久前有人谈论添加它们,但它似乎从未成为榜首。

    • 现在 PowerShell 已经开源, GitHub 上已经出现了一个问题
    • 令牌&&||当前保留以供将来在 PowerShell 中使用,因此希望可以实现与 Bash 中相同的语法。
      (从 PSv5.1 开始,尝试类似会1 && 1产生错误消息The token '&&' is not a valid statement separator in this version.

为什么 PowerShell 的-andand-or不能替代&&and ||

Bash的控制运算符&&(短路逻辑与)和||(短路逻辑或)通过其退出代码隐式检查命令的成功状态,而不会干扰其输出流;例如:

ls / nosuchfile && echo 'ok'

无论ls输出 - stdout 输出(中的文件/)和 stderr 输出(尝试访问不存在的文件的错误消息nosuchfile) - 都会通过,但会&&检查命令的(不可见)退出代码ls确定echo命令是否- 控制操作员的 RHS &&- 应该被执行。

ls1在这种情况下报告退出代码,表示失败- 因为文件nosuchfile不存在 - 所以&&决定ls 失败,并通过应用短路,决定echo不需要执行命令。
请注意,在and0的世界中,退出代码表示成功,而任何非零退出代码都表示失败。cmd.exebash

换句话说:Bash 的&&||操作完全独立于命令的输出,只对命令的成功状态起作用。


相比之下,PowerShell 的-andand仅作用于命令的标准(成功)输出使用-or,然后仅输出操作的布尔结果;例如:

(Get-ChildItem \, nosuchfile) -and 'ok'

以上:

  • 使用和消费成功(标准)输出——列表——并将其\解释为Boolean;在布尔上下文中考虑非空输入集合$true,因此如果至少有一个条目,则表达式的计算结果为$true.

    • 但是,由于文件不存在而导致的错误信息nosuchfile 传递,因为错误被发送到单独的流。
  • 鉴于Get-ChildItem \, nosuchfile返回非空成功输出,LHS 评估为$true,因此-and也评估 RHS ,'ok'但同样,消耗其输出并将其解释为布尔值,作为非空字符串,也评估为$true

  • 因此,-and表达式的整体结果是$true,这是(唯一成功的)输出

净效果是:

  • 表达式双方的成功输出在评估期间被消耗,因此被有效隐藏-and

  • 表达式的唯一(成功)输出是它的 Boolean result$true在这种情况下是(True在终端中呈现)。

于 2017-01-23T21:51:18.823 回答
12

Bash 必须做的是在传递给逻辑运算符时将命令的退出代码隐式转换为布尔值。PowerShell 不这样做 - 但可以创建一个函数来包装命令并创建相同的行为:

> function Get-ExitBoolean($cmd) { & $cmd | Out-Null; $? }

$? 是一个布尔值,包含最后一个退出代码的成功

给定两个批处理文件:

#pass.cmd
exit

#fail.cmd
exit /b 200

...可以测试行为:

> if (Get-ExitBoolean .\pass.cmd) { write pass } else { write fail }
pass
> if (Get-ExitBoolean .\fail.cmd) { write pass } else { write fail }
fail

逻辑运算符的计算方式应与 Bash 中的相同。首先,设置一个别名:

> Set-Alias geb Get-ExitBoolean

测试:

> (geb .\pass.cmd) -and (geb .\fail.cmd)
False
> (geb .\fail.cmd) -and (geb .\pass.cmd)
False
> (geb .\pass.cmd) -and (geb .\pass.cmd)
True
> (geb .\pass.cmd) -or (geb .\fail.cmd)
True
于 2010-03-10T12:43:31.727 回答
-2

我们可以使用 try catch finally 方法而不是在 powershell 中使用 && 方法。

try {hostname} catch {echo err} finally {ipconfig /all | findstr bios}
于 2017-01-21T16:32:35.303 回答
-2

你可以做这样的事情,用 [void] 隐藏布尔输出,只得到副作用。在这种情况下,如果 $a 或 $b 为空,则将 $c 分配给 $result。赋值可以是表达式。

$a = ''
$b = ''
$c = 'hi'

[void](
  ($result = $a) -or
  ($result = $b) -or
  ($result = $c))

$result

输出

hi
于 2019-09-07T14:27:13.393 回答