PowerShell передает все параметры, полученные в функции, и обрабатывает параметры с пробелами - PullRequest
2 голосов
/ 12 июля 2020

Я новичок в PowerShell. В Msys2 (или Lnux) я определил функцию npp

npp ()
{
    ${NPP_PATH} "$@"
}

так, что если я вызываю из командной строки npp, она запускает Notepad ++ (как определено в ${NPP_PATH}). Если я позвоню npp "mydir/stage 1/a.txt", он откроет этот файл для редактирования. Вообще говоря, он позволяет:

  1. Любое количество параметров.
  2. Параметры, содержащие пробелы, если они экранированы соответствующим образом.

Что будет эквивалент в PowerShell?

Я думаю, что в PS я должен также go для функции, чтобы получить аналогичное поведение. До сих пор я мог получить неопределенное количество параметров и использовать их в foreach l oop, см. Код ниже. Но я не смог найти эквивалент простого "$@" для передачи всех параметров по мере их получения. Более того, если я использую кавычки в одном из аргументов, они удаляются, поэтому вероятно возникнут проблемы с путями к файлам, включая пробелы.

function multi_params {
    param(
        [Parameter(
            ValueFromRemainingArguments=$true
        )][string[]]
        $listArgs
    )
    $count = 0
    foreach($listArg in $listArgs) {
        '$listArgs[{0}]: {1}' -f $count, $listArg
        $count++
    }
}

1 Ответ

5 голосов
/ 12 июля 2020

Предполагая, что NPP_PATH - это переменная среды , эквивалентная функция PowerShell будет:

function npp {
  & $env:NPP_PATH $args
}

Если NPP_PATH - имя обычной переменной PowerShell, используйте & $NPP_PATH $args.

& - это оператор вызова , который необходим для syntacti c причин всякий раз, когда вы хотите вызвать команду имя / путь которого указаны в кавычках и / или через переменную .

В простые функции (как в отличие от расширенных функций ), как указано выше (без использования атрибутов [CmdletBinding()] и [Parameter()]), вы можете использовать переменную automati c $args для передачи любых аргументов другой команде.

  • Если целевая команда не является внешней программой , например, здесь, а PowerShell , используйте форму @args, чтобы убедиться, что все аргументы, включая те, которым предшествуют их имена параметров , переданы правильно через - см. about_Splatting . Обратите внимание, что форма @args также работает с внешними программами, где это обычно эквивалентно $args (с той лишь разницей, что только @args распознает и удаляет --%, символ остановки анализа. )

  • Обратите внимание, что передача аргументов с встроенными " символами. и пустые аргументы * от 1064 * до внешние программы все еще не работает, начиная с PowerShell v7.0 - см. этот ответ .

Передача аргументов в простом против расширенном функциях (скриптах):

  • В простом только функции , $args содержит все аргументы, которые не были привязаны к объявленным параметрам, если таковые имеются, при вызове.

    • Если ваша простая функция не объявляет любые параметры, как в приведенном выше примере, $args содержит все аргументы, переданные при вызове.

    • Если ваша простая функция объявляет параметры (обычно через param(...)), $args содержит только те аргументы, которые не связаны с объявленными параметрами ; вкратце: он собирает любые аргументы, для которых ваша функция не объявила параметры.

    • Следовательно, $args - это простой механизм для сбора аргументов, не объявленных или известных заранее, для использования в самой функции - особенно если объявление параметров не стоит усилий - или для передачи этих аргументов другой команде.

    • Для передачи аргументов, содержащих с именем аргументы (например, -Path foo вместо просто foo) через другую команду PowerShell, требуется splatting , то есть форма @args.

      • Обратите внимание, что while $args технически является обычным массивом PowerShell ([object[]]), он также имеет встроенный magi c для поддержки передачи именованных аргументов; a настраиваемый массив может не для этого, и тогда требуется форма сплаттинга ha sh -table - см. about_Splatting
  • In расширенный функции , $args is not доступен , потому что расширенные функции по определению принимают только аргументы, для которых были объявлены параметры .

    • Чтобы принимать дополнительные, только позиционные аргументы, вы должен определять универсальный параметр ValueFromRemainingArguments, как показано в вопросе, который по умолчанию собирает такие аргументы в виде массива [1] структуры данных.

    • Чтобы также поддерживать именованные сквозные аргументы, у вас есть два основных параметра c:

      • Если вы знаете набор потенциальные сквозные параметры, объявите их как часть вашей собственной функции .

        • Затем вы можете использовать сплаттинг со словарем $PSBoundParameters (ha sh table) - см. Ниже - для передачи именованных аргументов, возможно, после удаления аргументов, предназначенных для самой вашей функции, из словаря.
      • Этот прием используется при написании прокси (оболочки) функций для существующих команд; Пакет SDK PowerShell упрощает дублирование параметров передачи, позволяя формировать функцию прокси на основе существующей команды - см. этот ответ .

    • В противном случае существует только субоптимальное решение, в котором вы имитируете собственный синтаксический анализ параметров PowerShell для синтаксического анализа позиционных аргументов в пары имя-параметр / значение - см. этот ответ .

Переменная automati c $PSBoundParameters - это словарь, который доступен в как в простых, так и в расширенных функциях:

  • $PSBoundParameters применяется, только если ваша функция объявляет параметры, а содержит записи только для тех среди объявленных параметров , к которым аргументы были фактически привязаны (переданы) при вызове ; ключи словаря - это имена параметров, хотя и без начального -. Обратите внимание, что параметры, связанные значением по умолчанию , не включены - см. этот выпуск GitHub для обсуждения. Опять же, обратите внимание, что в расширенных функциях вы можете передавать данный аргумент, только если для него был объявлен параметр, поэтому любой аргумент, переданный в данном вызове, по определению отражается в $PSBoundParameters.

  • Поскольку это словарь (ha sh таблица), его можно использовать со сплатингом на основе ha sh - @PSBoundParameters - для передачи именованных аргументов другим командам PowerShell и, поскольку это изменяемый , у вас есть возможность добавить или удалить именованные аргументы (например, те, которые предназначены для вашей функции сама ).

[1] Это тип [System.Collections.Generic.List[object]]; однако вы можете явно указать тип коллекции, например [object[]], чтобы получить обычный массив PowerShell.

...