Powershell non-positional, необязательные параметры - программирование
Подтвердить что ты не робот

Powershell non-positional, необязательные параметры

Я пытаюсь создать powershell (2.0) script, который будет принимать аргументы, которые следуют этому базовому шаблону:

.\{script name} [options] PATH

Где варианты - любое количество необязательных параметров - подумайте по строкам '-v' для подробного описания. Аргумент PATH будет просто любым аргументом, который передается последним, и является обязательным. Можно было вызвать script без параметров и только один аргумент, и этот аргумент будет считаться Путем. У меня возникли проблемы с настройкой списка параметров, который содержит только необязательные параметры, но также не является позиционным.

Этот быстрый script демонстрирует проблему, с которой я сталкиваюсь:

#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

Выходы script:

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

Поведение, которое я пытаюсь создать, будет иметь оба аргумента, которые попадают в необязательные параметры и заканчиваются в переменной остальныхArgs.

Этот вопрос/ответ предоставил способ достижения желаемого поведения, но он работает только в том случае, если есть хотя бы один обязательный параметр, и только если он предшествует всем другим аргументам.

Я могу продемонстрировать это поведение, сделав 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

Первый обязательный аргумент присваивается, и все оставшееся происходит полностью.

Возникает вопрос: как настроить список параметров таким образом, чтобы все параметры были необязательными, и ни один из них не является позиционным?

4b9b3361

Ответ 1

Как насчет этого?

function test
{
   param(
      [string] $One,

      [string] $Two,

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

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

One и Two являются необязательными и могут указываться только по имени. 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]