【问题标题】:Powershell equivalent of Bash "Alternate Value"等效于 Bash“替代值”的 Powershell
【发布时间】:2021-09-07 06:31:52
【问题描述】:

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

在 Bash 中,您可以执行以下操作(来自 this question):

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

因此,如果定义了PARAMS,它将仅包含--data 开关和参数。 Powershell 中是否有与此等价的功能?

【问题讨论】:

  • 这是您的实际用例还是只是一个虚构的例子? PowerShell 不像 bash 那样进行内联变量修改,但它有许多 other 工具用于有条件地传递/代理 args。他们是否会解决您的问题取决于上下文。你只传递[string] 参数吗?目标命令始终是二进制/可执行文件,还是 PowerShell 命令/cmdlet/函数?

标签: powershell parameter-passing parameter-expansion


【解决方案1】:

正如 Mathias 所说,PowerShell没有直接等同于 Bash 的 parameter expansionGithub issue #9566 讨论了将来可能为 PowerShell 带来类似功能。

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

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

这利用了以下行为:

  • 使用$(...)subexpression operator 将任意语句的输出作为命令参数传递的能力;请注意,对于简单的表达式命令只需(...)grouping operator就足够了。

    • 如果这样的$(...)(...) 参数产生没有输出(实际上是$null),没有参数在调用外部程序时被传递 ;在目前的情况下,这适用于if ($PARAMS) 条件评估为$false,即如果$PARAMS 是“假”,则基于PowerShell's to-Boolean coercion rules

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

  • 数组作为参数传递给外部程序会导致数组元素作为单个参数传递。


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

  • 数组被视为单个参数,它们作为一个整体传递

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

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

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

  • 要动态传递位置(未命名)参数,请将喷溅变量定义为数组(例如$dynArgs = 'foo', 'bar'

  • 要动态传递命名参数(参数前面是目标参数名称),请将喷溅变量定义为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 的内置别名,它隐藏 Windows 附带的外部curl.exe 实用程序。但是,通过使用curl.exe 进行调用(即通过显式包含文件扩展名),可以绕过别名。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-01
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 2022-12-09
    • 1970-01-01
    • 2013-02-18
    相关资源
    最近更新 更多