从命令行将多个参数传递给Powershell函数?

时间:2018-02-08 00:13:56

标签: powershell

我正在编辑脚本函数以添加名为CloneGitPackage的函数。这是我写的功能:

function CloneGitPackage {
    $PACKAGE_URL = $args[1]
    $PACKAGE_NAME = $args[2]

    write-verbose "Downloading package: $PACKAGE_URL $PACKAGE_NAME"
    git clone --depth 1 $PACKAGE_URL $PACKAGE_NAME 2>$null
    write-verbose ""
}

但原始脚本还有其他一些功能:

[CmdletBinding()]
param(
    [Parameter(Mandatory = $false, Position = 0)]
    [string]$command,
    [Parameter(Mandatory = $false)]
    [switch] $coverage
)

...

try{
    switch ($command){
        "bootstrap" { Bootstrap }
        "install" { Install }
        "run_tests" { RunTests }
        "clone_git_package" { CloneGitPackage }
    }
}catch {
    throw $_
}

我正在调用这样的脚本:

 .\script.ps1 "clone_git_package" "https://github.com" "Folder" -verbose

但它抱怨道:

script.ps1 : A positional parameter cannot be found that accepts argument 'https://github.com'.
At line:1 char:19
+ ... .\script.ps1 "clone_git_package" "https://github.com/ ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [script.ps1], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,script.ps1

Command executed with exception: A positional parameter cannot be found that accepts argument 'https://github.com'.

我认为问题是原始脚本已有的陌生人标题:

[CmdletBinding()]
param(
    [Parameter(Mandatory = $false, Position = 0)]
    [string]$command,
    [Parameter(Mandatory = $false)]
    [switch] $coverage
)

这些是对脚本的一些有效调用:

  1. .\script.ps1 "bootstrap" -verbose
  2. .\script.ps1 "install" -verbose
  3. .\script.ps1 "run_tests" -coverage -verbose
  4. 我需要能够调用传递新函数名称的脚本,在这种情况下clone_git_package并提供其参数,字符串git URL和另一个字符串directory name

    如何解决这个问题,而不会破坏与已经使用过这些内容的脚本上的其他内容的向后兼容性?

2 个答案:

答案 0 :(得分:2)

为了能够将参数传递给您的函数,您需要更新脚本的参数以适应您的其他参数。那么让我们从你的函数参数开始吧。现在你参考:

$PACKAGE_URL = $args[1]
$PACKAGE_NAME = $args[2]

这不是特别好的脚本。更好的选择是为您的函数创建实际参数:

function CloneGitPackage {
Param(
    $PACKAGE_URL,
    $PACKAGE_NAME
)

这基本上与您之前做过的事情相同,因为参数的位置基于它们列出的顺序。我们可以变得更加漂亮,但实际上没有必要。因此,如果我们将相同的逻辑应用于脚本的参数,那就像(将开关保持在底部,使其成为最后一个预期的参数):

param(
    [Parameter(Mandatory = $false, Position = 0)]
    [string]$command,
    $PACKAGE_URL,
    $PACKAGE_NAME,
    [Parameter(Mandatory = $false)]
    [switch] $coverage
)

现在,当您为其提供附加信息时,脚本知道如何处理您的参数!之后,您只需要更新脚本调用函数的方式,以便在调用它时包含这些参数,并且您应该全部设置。

switch ($command){
    "bootstrap" { Bootstrap }
    "install" { Install }
    "run_tests" { RunTests }
    "clone_git_package" { CloneGitPackage $PACKAGE_URL $PACKAGE_NAME }
}

答案 1 :(得分:0)

我这样做了,似乎工作正常:

[CmdletBinding()]
param(
    [Parameter(Mandatory = $false, Position = 0)]
    [string]$command,
    [Parameter(Mandatory = $false, Position = 1)]
    [string]$package_url,
    [Parameter(Mandatory = $false, Position = 2)]
    [string]$package_name,
    [Parameter(Mandatory = $false)]
    [switch] $coverage
)

...

function CloneGitPackage {
    $PACKAGE_PATH = "$TARGET_FOLDER\$package_name"

    write-verbose "Downloading package: $package_url $PACKAGE_PATH"
    git clone --depth 1 $package_url $PACKAGE_PATH 2>$null
    write-verbose ""
}

try{
    switch ($command){
        "bootstrap" { Bootstrap }
        "install" { Install }
        "run_tests" { RunTests }
        "clone_git_package" { CloneGitPackage }
    }
}catch {
    throw $_
}

将其称为:

  1. .\script.ps1 "bootstrap" -verbose
  2. .\script.ps1 "install" -verbose
  3. .\script.ps1 "run_tests" -coverage -verbose
  4. .\script.ps1 "clone_git_package" "https://github.com" "Folder" -verbose