如何将多个parameter passing到PowerShell中的函数?
如果我有一个接受多个string参数的函数,那么第一个参数似乎会获得分配给它的所有数据,而其余的参数是空的。
快速testing脚本:
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中的函数(所有版本)中的参数是空格分隔的,而不是逗号分隔的。 另外,如果Set-StrictMode
处于活动状态,则括号完全是不必要的,并且会导致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
已经提供了正确的答案,但是这个问题似乎普遍存在,为那些想要了解微妙之处的人们提供了一些额外的细节。 我会添加这个只是作为一个评论,但我想包括一个插图 – 我把它closuresPowerShell函数我的快速参考图表。 这假定函数f的签名是f($a, $b, $c)
:
因此,可以用空间分隔的位置参数或者与顺序无关的命名参数来调用函数。 其他的陷阱表明你需要认识逗号,括号和空格。
有关更多信息,请参阅我的文章Down the Rabbit Hole:刚刚发布在Simple-Talk.com上的PowerShellpipe道,函数和参数的研究。 该文章还包含快速参考/挂图的链接。
您可以调用没有括号的PowerShell函数,也不用逗号作为分隔符。 尝试使用:
test "ABC" "DEF"
在PowerShell中,逗号(,)是一个数组运算符,例如
$a = "one", "two", "three"
它将$ a设置为具有三个值的数组。
Function Test([string]$arg1, [string]$arg2) { Write-Host "`$arg1 value: $arg1" Write-Host "`$arg2 value: $arg2" } Test "ABC" "DEF"
如果您是C#/ Java / C ++ / Ruby / Python /从本世纪开始的开发人员,并且想用逗号来调用您的函数,因为这是您一直以来所做的事情,那么您需要一些东西喜欢这个:
$myModule = new-module -ascustomobject { function test($arg1, $arg2) { echo "arg1 = $arg1, and arg2 = $arg2" } }
现在致电:
$myModule.test("ABC", "DEF")
你会看到的
arg1 = ABC, and arg2 = DEF
如果你尝试:
PS > Test("ABC", "GHI") ("DEF")
你得到:
$arg1 value: ABC GHI $arg2 value: DEF
所以你看到括号分开参数
如果你尝试:
PS > $var = "C" PS > Test ("AB" + $var) "DEF"
你得到:
$arg1 value: ABC $arg2 value: DEF
现在你可以发现括号的一些直接的用处 – 一个空格不会成为下一个参数的分隔符 – 相反,你有一个eval函数。
这里有一些很好的答案,但我想指出一些其他的事情。 函数参数实际上是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
第一个例子工作,即使名称是第二个,因为我们明确使用参数名称。 第二个例子是基于位置的,所以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,但不是两个。 您可以在位置上或按名称使用它们。 由于它们是不同的types,因此PowerShell将会计算出来。 所有这些都可以工作
Get-Something "some name" Get-Something 23 Get-Something -Name "some name" Get-Something -Id 23
您还可以将其他参数分配给各种参数集。 (这显然是一个非常基本的例子)在函数内部,你可以确定哪个参数集与$ PsCmdlet.ParameterSetName属性一起使用。 例如:
if($PsCmdlet.ParameterSetName -eq "Name") { Write-Host "Doing something with name here" }
然后,在相关的一面注意到,在PowerShell中也有参数validation。 这是我最喜欢的PowerShellfunction之一,它使你的函数中的代码非常干净。 有许多validation你可以使用。 几个例子是
function Get-Something { Param ( [Parameter(Mandatory=$true, Position=0)] [ValidatePattern('^Some.*')] [string] $Name, [Parameter(Mandatory=$true, Position=1)] [ValidateRange(10,100)] [int] $Id ) }
在第一个例子中,ValidatePattern接受一个正则expression式,确保提供的参数与你所期望的相符。 如果没有,就会抛出一个直观的exception,告诉你到底发生了什么错误。 所以在这个例子中,“Something”可以正常工作,但是“Summer”不能通过validation。
ValidateRange确保参数值位于您期望的整数范围之间。 所以10或99会工作,但101会抛出exception。
另一个有用的是ValidateSet,它允许你显式地定义一个可接受值的数组。 如果input了其他内容,则会抛出exception。 还有其他的,但可能最有用的是ValidateScript。 这需要一个脚本块,必须评估为$ true,所以天空是极限。 例如:
function Get-Something { Param ( [Parameter(Mandatory=$true, Position=0)] [ValidateScript({ Test-Path $_ -PathType 'Leaf' })] [ValidateScript({ (Get-Item $_ | select -Expand Extension) -eq ".csv" })] [string] $Path ) }
在这个例子中,我们不仅保证$ Path存在,而且它是一个文件(与一个目录相对)并且具有.csv扩展名。 ($ _指的是参数,当你的脚本块内。)你也可以传递更大,多行脚本块,如果需要的水平,或使用多个脚本块,如我在这里做的。 这是非常有用的,并使良好的清洁function和直观的例外。
我不知道你在做什么function,但看看使用“param”关键字。 将parameter passing给一个函数是相当强大的,并且使用户更友好。 下面是微软有关它的一篇过于复杂的文章的链接。 这并不像文章所说的那样复杂。 参数用法
另外,这里是一个来自这个网站的主题的例子:
一探究竟。
Function Test([string]$arg1, [string]$arg2) { Write-Host "`$arg1 value: $arg1" Write-Host "`$arg2 value: $arg2" } Test("ABC") ("DEF")
我早些时候说过:
常见的问题是使用单数forms$arg
,这是不正确的。
它应该总是复数$args
。
问题不在于此。
事实上, $arg
可以是其他任何东西。 问题在于使用了逗号和缺位。
我运行下面的代码工作,输出如下:
码:
Function Test([string]$var1, [string]$var2) { Write-Host "`$var1 value: $var1" Write-Host "`$var2 value: $var2" }
testing“ABC”“DEF”
输出:
$ var1值:ABC $ var2值:DEF
你也可以像这样在函数中传递参数 。
function FunctionName() { Param ([string]$ParamName); #Operations }
如果你不知道(或关心)你将传递给函数的参数有多less,你也可以使用一个非常简单的方法:
代码 :
function FunctionName() { Write-Host $args }
这将打印出所有的论据。 例如:
FunctionName abc 1 2 3
产量
abc 1 2 3
我发现这在创build使用外部命令的函数时特别有用,这些外部命令可能有许多不同的(和可选的)参数,但依赖于所述的命令来提供关于语法错误的反馈等。
这是另外一个真实世界的例子(为tracert命令创build一个函数,我讨厌不得不记住截断的名字);
代码 :
Function traceroute { Start-Process -FilePath "$env:systemroot\system32\tracert.exe" -ArgumentList $args -NoNewWindow }
Function Test { Param([string]$arg1, [string]$arg2) Write-Host $arg1 Write-Host $arg2 }
这是正确的参数声明https://technet.microsoft.com/en-us/library/dd347600.aspx
这确实有效
因为这是一个经常被查看的问题,所以我想提一下PowerShell函数应该使用经过批准的动词 ( Verb-Noun作为函数名)。 你也可以指定参数是否是强制参数和参数的位置 :
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" }
要将parameter passing给函数,您可以使用以下位置 :
Test-Script "Hello" "World"
或者你指定参数名称 :
Test-Script -arg1 "Hello" -arg2 "World"
在C#中调用函数时,不要像使用括号一样使用括号 。
我build议在使用多于一个参数时始终传递参数名称,因为这样更具可读性 。