5

I would like to create a Powershell script that takes parameters in the standard Linux style, i.e., --my-param, with a leading --. I thought this might be possible using the alias parameter attribute, as in

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

What I hoped with this was that the call

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

would be recognized as referring to the alias -my-param. Unfortunately, what I get is

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

On the other hand, using the alias my-param in this lets me call the script with -my-param. Is there a way of specifying parameter names with leading -- in Powershell?

4

2 回答 2

5

您的语法在标记器级别失败。相比:

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

...和...

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

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

于 2013-09-21T18:44:05.900 回答
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] 为空。

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

于 2013-09-21T21:16:15.647 回答