Как использовать аргумент тире в Powershell? - PullRequest
3 голосов
/ 25 июня 2019

Я портирую скрипт из 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., который затем выполняет более сложную обработку.

Ответы [ 2 ]

3 голосов
/ 25 июня 2019

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

1 голос
/ 25 июня 2019

Как отступление: PowerShell допускает удивительный диапазон имен переменных, но вы должны заключить их в {...}, чтобы они могли быть распознаны; то есть ${-} технически работает, но это не решает вашу проблему.

Проблема в том, что PowerShell тихо удаляет -- из списка аргументов - и единственный способ сохранить , что этот токен - это вы ему предшествует символ остановки разбора PSv3 + , --%, который, однако, в корне меняет способ передачи аргументов и, очевидно, является дополнительным требованием, которое вы пытаетесь избежать.

Лучше всего попробовать - неоптимальный - обходные пути :

  • Вариант 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, как правило, следует избегать .

Если ваш скрипт называется foo.ps1 и вы вызвали его как ./foo.ps1 -- -args go -here, вы увидите следующий вывод:

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