Powershell 相当于 Bash "Alternate Value"

Powershell equivalent of Bash "Alternate Value"

我正在尝试在具有可选开关的 Powershell 脚本中调用一个命令,它必须动态确定是否包含这些开关。

在Bash中,你可以这样做(来自this question):

curl -o - ${PARAMS:+"--data" "$PARAMS"}

因此,如果定义了 PARAMS,它只会包含 --data 开关和参数。 Powershell 中是否有与此等效的内容?

正如 Mathias 所说,PowerShell 没有 直接等同于 Bash 的 parameter expansion. Possibly bringing a similar feature to PowerShell in the future is discussed in Github issue #9566

如果您正在调用 外部程序,例如 curl[1](而不是 PowerShell cmdlet/script/function),您可以使用以下方法:

curl -o - $(if ($PARAMS) { '--data', $PARAMS })

这利用了以下行为:

  • 能够将任意语句的输出作为命令参数传递,使用$(...)subexpression operator; note that for simple expressions and commands just (...), the grouping operator就足够了。

    • 如果这样的$(...)(...)参数产生无输出(实际上是$null),调用外部程序时没有传递参数;在手头的情况下,如果 if ($PARAMS) 条件评估为 $false,即如果 $PARAMS 是“假的”,基于 .

    • 注意:如果 $PARAMS 可以包含非字符串值,例如 0,也将被视为 $false,请使用更明确的条件:if ($null -ne $PARAMS),只有 $true 如果 $PARAMSundefined(或明确包含 $null)。

  • 数组作为参数传递给外部程序导致数组元素作为传递个别论点.


请注意,调用 PowerShell 本机命令时适用不同的规则(cmdlet、脚本、函数):

  • 数组被认为是单个参数,作为一个整体传递。

  • 您不能通过变量或表达式传递参数 names(例如,-Body)。

这两个问题的解决方案是使用splatting:

这涉及首先将动态参数存储在 变量 中,然后通过 @ 而不是 $ 传递(例如,定义变量 $dynArgs 并将其作为 @dynArgs) 传递,它有两种形式:

  • 要动态传递 positional(未命名)参数,将 splatting 变量定义为 array(例如 $dynArgs = 'foo', 'bar')

  • 要动态传递 named 参数(参数以其目标参数名称开头),将 splatting 变量定义为 hashtable.

因此,如果您要调用 Invoke-RestMethod 而不是 curl,并且您希望有条件地传递 -Body 参数,您可以执行如下操作:

$dynArgs = @{} # Initialize a hashtable

# Conditionally create a 'Body' entry. The key name
# must match the target parameter (without "-"):
if ($PARAMS) { $dynArgs['Body'] = $PARAMS }

# Pass $dynArgs via *splatting* - note the "@" sigil.
# If the hashtable is empty, nothing is passed.
# Splatting can be *combined* with directly passed arguments
# (symbolized by "..." here).
Invoke-RestMethod @dynArgs ...

[1] 请注意,在 Windows PowerShell curl 中(不幸的是)是 Invoke-WebRequest cmdlet,它 shadows 现在 Windows 附带的外部 curl.exe 实用程序。但是,通过使用 curl.exe 进行调用(即通过显式包含文件扩展名),可以绕过别名。