PowerShell非位置参数和可选参数

24

我正在尝试创建一个 PowerShell (2.0) 脚本,该脚本将接受遵循此基本模式的参数:

.\{script name} [options] PATH

其中选项是任意数量的可选参数,类似于详细模式的'-v'。PATH参数将简单地是最后传入的任何参数,并且是强制性的。可以使用不带任何选项且仅有一个参数的方式调用脚本,那个参数将被假定为路径。我无法设置仅包含可选参数但又非位置参数的参数列表。

这个简短的脚本演示了我所遇到的问题:

#param test script
Param(
    $firstArg,
    $secondArg,
    [switch]$thirdArg,
    [Parameter(ValueFromRemainingArguments = $true)]
    $remainingArgs)

write-host "first arg is $firstArg"
write-host "second arg is $secondArg"
write-host "third arg is $thirdArg"
write-host "remaining: $remainingArgs"

当像这样调用时:

.\param-test.ps1 firstValue secondValue
脚本输出:
first arg is firstValue
second arg is secondValue
third arg is False
remaining:

我想要实现的行为是,两个参数都可以通过可选参数传递,并最终进入remainingArgs变量。

这个问题/答案 给出了一个有用的方法来实现所需的行为,但它似乎只在至少有一个必需参数且该参数出现在所有其他参数之前时才起作用。

我可以通过将firstArg设为必需参数并指定位置0来演示这种行为:

#param test script
Param(
    [Parameter(Mandatory=$true, Position = 0)]
    $firstArg,
    $secondArg,
    [switch]$thirdArg,
    [Parameter(ValueFromRemainingArguments = $true)]
    $remainingArgs)

    write-host "first arg is $firstArg"
    write-host "second arg is $secondArg"
    write-host "third arg is $thirdArg"
    write-host "remaining: $remainingArgs"

使用与之前相同的输入运行:

.\param-test.ps1 firstValue secondValue

输出如下:

first arg is firstValue
second arg is
third arg is False
remaining: secondValue

第一个必要参数被分配,其余的所有参数都被全部忽略。

问题是:我如何设置参数列表,使得所有参数都是可选的,且没有参数是位置参数?

1个回答

39

这个怎么样?

function test
{
   param(
      [string] $One,

      [string] $Two,

      [Parameter(Mandatory = $true, Position = 0)]
      [string] $Three
   )

   "One = [$one]  Two = [$two]  Three = [$three]"
}
< p >OneTwo是可选的,只能通过名称指定。 Three是必需的,可以不带名称提供。

这些是有效的:

test 'foo'
    One = []  Two = []  Three = [foo]
test -One 'foo' 'bar'
    One = [foo]  Two = []  Three = [bar]
test 'foo' -Two 'bar'
    One = []  Two = [bar]  Three = [foo]

这将失败:

test 'foo' 'bar'
test : A positional parameter cannot be found that accepts argument 'bar'.
At line:1 char:1
+ test 'foo' 'bar'
+ ~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [test], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,test

这并不会强制要求你的必填参数放在最后或者不带名称。但它允许你使用你想要的基本用法。

它也不允许$Three中有多个值。这可能是你想要的。但是,如果你想把多个非命名参数视为$Three的一部分,则需要添加ValueFromRemainingArguments属性。

function test
{
   param(
      [string] $One,

      [string] $Two,

      [Parameter(Mandatory = $true, Position = 0, ValueFromRemainingArguments = $true)]
      [string] $Three
   )

   "One = [$one]  Two = [$two]  Three = [$three]"
}

现在像这样的事情可以工作:

test -one 'foo' 'bar' 'baz'
  One = [foo]  Two = []  Three = [bar baz]
甚至可以。
test 'foo' -one 'bar' 'baz'
    One = [bar]  Two = []  Three = [foo baz]

3
正是我所需要的。我没有想到我可以使用一个强制参数,并将其放在最后一个参数位置=0。 - Fopedush
1
谢谢Latkin,我已经在这上面浪费了一个小时。我还有另一个问题(我已经在这里回答并感谢你):https://dev59.com/oXbZa4cB1Zd3GeqPL_Vp - ekkis
我知道这已经是几年后的事了,但是这个答案让我在花费了将近一个小时寻找如何使用任意数量的参数来完成此操作之后得救了。 - Paul

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接