如何将多个参数传递到PowerShell中的函数中?

如何将多个参数传递到PowerShell中的函数中?,powershell,syntax,parameter-passing,Powershell,Syntax,Parameter Passing,如果我有一个接受多个字符串参数的函数,那么第一个参数似乎获得了分配给它的所有数据,其余的参数则作为空参数传入 快速测试脚本: Function Test([string]$arg1, [string]$arg2) { Write-Host "`$arg1 value: $arg1" Write-Host "`$arg2 value: $arg2" } Test("ABC", "DEF") 生成的输出是 $arg1 value: ABC DEF $arg2 value: 正

如果我有一个接受多个字符串参数的函数,那么第一个参数似乎获得了分配给它的所有数据,其余的参数则作为空参数传入

快速测试脚本:

Function Test([string]$arg1, [string]$arg2)
{
    Write-Host "`$arg1 value: $arg1"
    Write-Host "`$arg2 value: $arg2"
}

Test("ABC", "DEF")
生成的输出是

$arg1 value: ABC DEF
$arg2 value: 
正确的输出应为:

$arg1 value: ABC
$arg2 value: DEF

在多台机器上,v1和v2之间似乎是一致的,所以很明显,我做错了什么。有人能确切指出什么吗?

调用PowerShell(所有版本)中的函数时,参数是以空格分隔的,而不是以逗号分隔的。此外,括号是完全不必要的,如果
-Version 2
或更高版本处于活动状态,则会在PowerShell 2.0(或更高版本)中导致分析错误。括号内的参数仅在.NET方法中使用

function foo($a, $b, $c) {
   "a: $a; b: $b; c: $c"
}

ps> foo 1 2 3
a: 1; b: 2; c: 3

调用PowerShell函数时不使用括号,也不使用逗号作为分隔符。尝试使用:

test "ABC" "DEF"
在PowerShell中,逗号(,)是一个数组运算符,例如

$a = "one", "two", "three"

它将
$a
设置为一个包含三个值的数组。

我不知道您对该函数做了什么,但请看一下如何使用“param”关键字。在将参数传递到函数中时,它的功能要强大得多,并且使它更加用户友好。下面是微软关于它的一篇过于复杂的文章的链接。这并不像文章说的那么复杂

此外,以下是本网站上的一个示例:

查看它。

如果您尝试:

Function Test([string]$arg1, [string]$arg2)
{
    Write-Host "`$arg1 value: $arg1"
    Write-Host "`$arg2 value: $arg2"
}

Test "ABC" "DEF"
PS > Test("ABC", "GHI") ("DEF")
PS > $var = "C"
PS > Test ("AB" + $var) "DEF"
你会得到:

$arg1 value: ABC GHI
$arg2 value: DEF
可见括号分隔了参数


如果您尝试:

PS > Test("ABC", "GHI") ("DEF")
PS > $var = "C"
PS > Test ("AB" + $var) "DEF"
你会得到:

$arg1 value: ABC
$arg2 value: DEF

现在,您可以立即发现括号的一些用处-空格不会成为下一个参数的分隔符-而是有一个eval函数。

已经提供了正确的答案,但这个问题似乎非常普遍,足以为那些想要了解其微妙之处的人提供一些额外的细节

我本想添加这个作为一个注释,但我想包括一个说明——我从PowerShell函数的快速参考图表中撕下了这个。这假设函数f的签名是
f($a,$b,$c)

因此,可以使用空间分隔的位置参数或顺序独立的命名参数调用函数。其他缺陷表明,您需要注意逗号、括号和空格


进一步阅读,请参阅我的文章。这篇文章还包含一个指向快速参考/挂图的链接。

我之前说过:

常见的问题是使用单数形式
$arg
,这是不正确的。它应该始终是复数形式,如
$args

问题不是这样。事实上,
$arg
可以是其他任何内容。问题在于逗号和括号的使用

我运行了以下有效的代码,输出如下:

代码:

Function Test([string]$var1, [string]$var2)
{
    Write-Host "`$var1 value: $var1"
    Write-Host "`$var2 value: $var2"
}
$var1 value: ABC
$var2 value: DEF
测试“ABC”“DEF”

输出:

Function Test([string]$var1, [string]$var2)
{
    Write-Host "`$var1 value: $var1"
    Write-Host "`$var2 value: $var2"
}
$var1 value: ABC
$var2 value: DEF
如果你是C++的爪哇/C++/Ruby/Python/PAC-A语言,你是本世纪的开发者,你想用逗号来调用你的函数,因为这是你一直以来所做的,那么你需要这样的东西:

$myModule = New-Module -ascustomobject { 
    function test($arg1, $arg2) { 
        echo "arg1 = $arg1, and arg2 = $arg2"
    }
}
现在请致电:

$myModule.test("ABC", "DEF")
你会看到的

arg1 = ABC, and arg2 = DEF

您可以在函数中传递参数,如下所示:

function FunctionName()
{
    Param ([string]$ParamName);
    # Operations
}
如果您不知道(或不关心)将向函数传递多少个参数,也可以使用非常简单的方法,如

代码

function FunctionName()
{
    Write-Host $args
}
Function traceroute
{
    Start-Process -FilePath "$env:systemroot\system32\tracert.exe" -ArgumentList $args -NoNewWindow
}
Test-Script "Hello" "World"
Test-Script -arg1 "Hello" -arg2 "World"
这将打印出所有的参数。例如:

FunctionName a b c 1 2 3
if($PsCmdlet.ParameterSetName -eq "Name")
{
    Write-Host "Doing something with name here"
}
function Get-Something
{
    Param
    (
         [Parameter(Mandatory=$true, Position=0)]
         [ValidateScript({ Test-Path $_ -PathType 'Leaf' })]
         [ValidateScript({ (Get-Item $_ | select -Expand Extension) -eq ".csv" })]
         [string] $Path
    )
}
输出

a b c 1 2 3
我发现这在创建使用外部命令的函数时特别有用,这些命令可能有许多不同的(可选)参数,但依赖于所述命令提供语法错误反馈等

这里是另一个真实的例子(为tracert命令创建一个函数,我讨厌记住被截断的名称)

代码

function FunctionName()
{
    Write-Host $args
}
Function traceroute
{
    Start-Process -FilePath "$env:systemroot\system32\tracert.exe" -ArgumentList $args -NoNewWindow
}
Test-Script "Hello" "World"
Test-Script -arg1 "Hello" -arg2 "World"

因为这是一个经常被浏览的问题,所以我想提一下PowerShell函数应该使用(动词-名词作为函数名)。 名称的动词部分标识cmdlet执行的操作。名称的名词部分标识执行操作的实体。此规则简化了高级PowerShell用户对cmdlet的使用

此外,还可以指定参数是否为必填项以及参数的位置:

function Test-Script
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory=$true, Position=0)]
        [string]$arg1,

        [Parameter(Mandatory=$true, Position=1)]
        [string]$arg2
    )

    Write-Host "`$arg1 value: $arg1"
    Write-Host "`$arg2 value: $arg2"
}

要将参数传递给函数,可以使用位置

function FunctionName()
{
    Write-Host $args
}
Function traceroute
{
    Start-Process -FilePath "$env:systemroot\system32\tracert.exe" -ArgumentList $args -NoNewWindow
}
Test-Script "Hello" "World"
Test-Script -arg1 "Hello" -arg2 "World"
或者指定参数名称

function FunctionName()
{
    Write-Host $args
}
Function traceroute
{
    Start-Process -FilePath "$env:systemroot\system32\tracert.exe" -ArgumentList $args -NoNewWindow
}
Test-Script "Hello" "World"
Test-Script -arg1 "Hello" -arg2 "World"
不要像调用C#中的函数那样使用括号


我建议在使用多个参数时始终传递参数名,因为这样可读性更好

这是一个正确的
params
声明


这确实有效。

这里有一些很好的答案,但我想指出一些其他的事情。函数参数实际上是PowerShell的亮点。例如,您可以在高级函数中使用命名参数或位置参数,例如:

function Get-Something
{
    Param
    (
         [Parameter(Mandatory=$true, Position=0)]
         [string] $Name,
         [Parameter(Mandatory=$true, Position=1)]
         [int] $Id
    )
}
然后,您可以通过指定参数名来调用它,也可以只使用位置参数,因为您显式定义了它们。因此,这两种方法中的任何一种都会起作用:

Get-Something -Id 34 -Name "Blah"
Get-Something "Blah" 34
Get-Something "some name"
Get-Something 23
Get-Something -Name "some name"
Get-Something -Id 23
尽管第二个示例提供了
Name
,但第一个示例仍然有效,因为我们显式使用了参数名。第二个例子是基于位置的,所以
Name
必须是第一个。如果可能,我总是尝试定义位置,以便两个选项都可用

PowerShell还能够定义参数集。它使用此方法代替方法重载,同样非常有用:

function Get-Something
{
    [CmdletBinding(DefaultParameterSetName='Name')]
    Param
    (
         [Parameter(Mandatory=$true, Position=0, ParameterSetName='Name')]
         [string] $Name,
         [Parameter(Mandatory=$true, Position=0, ParameterSetName='Id')]
         [int] $Id
    )
}
现在,函数将采用名称或id,但不能同时采用两者。您可以按位置或按名称使用它们。既然他们