【问题标题】:How to use dash argument in Powershell?如何在 Powershell 中使用破折号参数?
【发布时间】:2019-11-07 02:27:00
【问题描述】:

我正在将脚本从 bash 移植到 PowerShell,并且我希望在两者中保持对参数解析的相同支持。在 bash 中,可能的参数之一是 --,我还想在 PowerShell 中检测该参数。但是,到目前为止,我尝试过的任何方法都没有奏效。我不能将它定义为 param($-) 这样的参数,因为这会导致编译错误。另外,如果我决定完全放弃 PowerShell 参数处理,只使用 $args 一切看起来都很好,但是当我运行该函数时,-- 参数丢失了。

Function Test-Function {
    Write-Host $args
}

Test-Function -- -args go -here # Prints "-args go -here"

我也知道$PSBoundParameters,但该值不存在,因为我无法绑定名为$- 的参数。这里有没有我可以尝试的其他机制或任何解决方案?

有关更多上下文,请注意我使用 PowerShell 是一个副作用。预计这不会用作普通的PowerShell命令,我也为此编写了一个批处理包装器,但是包装器的逻辑比我想批量编写的要复杂,因此批处理包装器只是调用PowerShell函数,然后执行更复杂的处理。

【问题讨论】:

  • 如果您将其称为 ${-params},您可以有一个名为 -params 之类的变量或参数,但是,我仍然不要认为您可以将双连字符参数传递给函数。
  • 这可行,但需要修改命令行参数,我想避免这样做。我想我可以检测到-- 被传入批处理脚本,然后将其批量转义到`--
  • 使用反引号“Test-Function `-- -args go -here”对我有用
  • 因此,虽然此线程中有大量信息,但我最终只是用 C# 编写了一个小包装器,并部署了一个 exe 包装器,而不是复杂的批处理->powershell->myprogram 设置。无论如何,这是一个 xy 问题,但答案仍然很有趣,并且希望将来可以帮助其他人!这样做也绕过了我遇到的其他一些问题,例如如何处理引号字符。

标签: powershell parameter-passing


【解决方案1】:

顺便说一句:PowerShell 允许使用令人惊讶的变量名范围,但您必须将它们括在 {...} 中才能被识别;也就是说,${-} 在技术上有效,但不能解决您的问题。

挑战在于 PowerShell 悄悄地删除 -- 从参数列表中 - 保留的唯一方法令牌是你在它前面加上 PSv3+ stop-parsing symbol, --%,但是,从根本上改变了参数的传递方式,显然是一个额外的要求,这是你试图避免的.

您最好的选择是尝试 - 次优 - 解决方法

  • 选项 A:在您的批处理文件包装器中,将 -- 转换为 PowerShell 确实 保留并传递它的特殊参数;然后,PowerShell 脚本必须将该特殊参数重新转换为 --

  • 选项 B:在 PowerShell 中执行自定义参数解析:

您可以分析$MyInvocation.Line,其中包含调用您的脚本的原始命令行,并在那里查找-- 的存在。

然而,正确处理并使其健壮并非易事。
这是一个合理稳健的方法:

# Don't use `param()` or `$args` - instead, do your own argument parsing:

# Extract the argument list from the invocation command line.
$argList = ($MyInvocation.Line -replace ('^.*' + [regex]::Escape($MyInvocation.InvocationName)) -split '[;|]')[0].Trim()

# Use Invoke-Expression with a Write-Output call to parse the raw argument list,
# performing evaluation and splitting it into an array:
$customArgs = if ($argList) { @(Invoke-Expression "Write-Output -- $argList") } else { @() }

# Print the resulting arguments array for verification:
$i = 0
$customArgs | % { "Arg #$((++$i)): [$_]" }

注意:

  • 毫无疑问,在某些极端情况下,可能无法正确提取参数列表或重新评估原始参数会导致副作用,但对于大多数情况 - 尤其是从 外部调用时 PowerShell - 这应该可以。

  • 虽然在这里有用,但Invoke-Expression should generally be avoided

如果您的脚本名为 foo.ps1 并且您将其调用为 ./foo.ps1 -- -args go -here,您将看到以下输出:

Arg #1: [--]
Arg #2: [-args]
Arg #3: [go]
Arg #4: [-here]

【讨论】:

  • 这太棒了!像 $MyInvocation.Line 这样的东西正是我所希望的!就我而言,我不介意在 powershell 中增加一点复杂性,而且无论如何我的用例相当有限,因为我仍然有能力在最终的底层程序中进行一些批处理和底层程序powershell 调用。
【解决方案2】:

我找到了一种方法,但是你必须传递其中的 3 个而不是双连字符。

这是一个简单的功能,你可以随意更改代码:

function Test-Hyphen {
    param(
        ${-}
    )
    if (${-}) {
        write-host "You used triple-hyphen"
    } else {
        write-host "You didn't use triple-hyphen"
    }
}

示例 1

Test-Hyphen

输出

You didn't use triple-hyphen

示例 2

Test-Hyphen ---

输出

You used triple-hyphen

【讨论】:

  • 这真的很奇怪,它需要 3 个破折号。但这仍然需要更改输入参数,这是我试图避免的。如果没有办法,我宁愿在这种情况下使用普通的命名参数。不过感谢您的回答。
  • ----- 不同,它对 PowerShell 来说并不特殊,因此它像任何其他字符串文字参数一样被传递;参数的名称是附带的(无需命名为${-})。
猜你喜欢
  • 2011-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-10
  • 2020-09-05
  • 2017-12-10
  • 1970-01-01
  • 2011-02-21
相关资源
最近更新 更多