【问题标题】:How to provide Linux-style parameter names in a powershell script如何在 powershell 脚本中提供 Linux 风格的参数名称
【发布时间】:2013-09-26 21:06:18
【问题描述】:

我想创建一个 Powershell 脚本,它采用标准 Linux 样式的参数,即 --my-param,带前导 --。我认为这可能使用别名参数属性,如

Param (
    [parameter(Mandatory=$true)]
    [alias("-my-param","p")]
    [String]
    $param
)

我希望这是电话

c:\src\ps\params.ps1 --my-param "x"

将被识别为引用别名 -my-param。不幸的是,我得到的是

C:\src\ps\params.ps1 : A positional parameter cannot be found that accepts argument 'x'.
At line:1 char:21
+ c:\src\ps\params.ps1 <<<<  --my-param1 "x"
    + CategoryInfo          : InvalidArgument: (:) [params.ps1], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,params.ps1

另一方面,使用别名 my-param 可以让我使用 -my-param 调用脚本。 有没有办法在 Powershell 中以 -- 开头指定参数名称?

【问题讨论】:

  • 您要解决什么问题?如果你想要一个表现得像 Linux shell 的 shell,安装 Cygwin 或其他已经移植到 Windows 的 Unix shell?否则,请坚持使用 PowerShell 的约定,否则可能会让熟悉 PowerShell 的人感到困惑。 IOW,坚持环境的成语,不要试图将其他环境的成语嫁接到它上面。
  • @alroc 完全不同的问题。这个问题是关于调用外部程序(在这种情况下是用 C# 编写的东西)的问题,使用来自 PowerShell 提示符的 -- 参数(其中这些参数 对于该外部程序是合法的,但 PowerShell 没有通过他们到程序)。这是关于让 PowerShell 脚本接受以 -- 开头的参数。这也是为什么像 Cygwin 这样的东西不是解决方案的原因。他不希望 shell 表现得像 Unix shell。大概他想在 PS 提示符下调用他的 PS 脚本,他只是希望它接受 -- 参数。
  • @alroc,Adi Inbar 是正确的。我想知道Powershell提供的自动参数处理是否有办法识别'--'参数。原因是我在 Windows 和 Linux 上都有做同样事情的脚本,Linux 在我工作的地方占主导地位,如果可以轻松自然地完成,所有脚本都使用主导平台的参数约定似乎是合理的。好像'--'是Powershell专门处理的,所以我会按照你的建议去做,并坚持每个平台的约定。
  • 我发现的各种以前的答案是指布鲁斯·佩耶特的书。但它指的是 '--' 本身作为一种参数停止器出现,而不是在较大标记开头的 '--' 的情况。

标签: powershell


【解决方案1】:

您的语法在分词器级别失败。比较:

[Management.Automation.PSParser]::Tokenize(
    'Command -parameter',
    [ref]$null
)

...和...

[Management.Automation.PSParser]::Tokenize(
    'Command --parameter',
    [ref]$null
)

如您所见,解析器将前者视为参数,后者 - 作为参数。 所以唯一的方法是“内部”解析所有参数并猜测什么是参数(从你的角度来看),什么是参数。

【讨论】:

  • 这是一个非常有帮助的答案。
【解决方案2】:

我不知道有任何库会为您解析 Unix 风格的参数(这并不一定意味着没有...),但您可以不声明任何参数并解析参数自己在脚本的正文中。

这将创建参数的哈希表,其中键是参数名称,值是参数值。开关参数将具有空值。

$params = @{}
$MyInvocation.Line.Substring(($MyInvocation.Line.IndexOf('--') + 2)) -split ' --' | %{
  $_ -match '(\S+) ?(.+)?' | Out-Null
  $params.($matches[1]) = $matches[2]
}
  • $MyInvocation.Line 为您提供用于调用脚本的命令行。 $MyInvocation.Line.Substring(($MyInvocation.Line.IndexOf('--') + 2)) 为您提供第一个 -- 之后的所有内容。
  • $_ -match '(\S+) ?(.+)?' 将参数名称分配给第一个匹配组,将值分配给第二个匹配组。 Out-Null 阻止 PowerShell 为每次迭代打印 True
  • 我使用(.+)? 而不是(.*) 的原因是让开关参数的值为空。 (.*) 将匹配空字符串,如果没有可匹配的内容,使 $matches[2] 的值是空字符串,而 (.+)? 将不匹配,使 $matches [2] 为空。

这是假设所有参数都以 -- 开头。如果您想允许使用单个连字符,将单破折号参数名称限制为单个字母,或者检查错误声明的参数(例如,如果存在三连字符则抛出错误),您必须在您的代码,但这是基本思想。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-19
    • 1970-01-01
    • 1970-01-01
    • 2021-03-25
    • 1970-01-01
    • 1970-01-01
    • 2021-07-07
    • 2015-05-29
    相关资源
    最近更新 更多