简体   繁体   English

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

[英]How do I pass multiple parameters into a function in PowerShell?

If I have a function which accepts more than one string parameter, the first parameter seems to get all the data assigned to it, and remaining parameters are passed in as empty.如果我有一个接受多个字符串参数的函数,则第一个参数似乎获取分配给它的所有数据,其余参数作为空传递。

A quick test script:快速测试脚本:

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

Test("ABC", "DEF")

The output generated is生成的输出是

$arg1 value: ABC DEF
$arg2 value: 

The correct output should be:正确的输出应该是:

$arg1 value: ABC
$arg2 value: DEF

This seems to be consistent between v1 and v2 on multiple machines, so obviously, I'm doing something wrong.这似乎在多台机器上的 v1 和 v2 之间是一致的,所以很明显,我做错了什么。 Can anyone point out exactly what?谁能指出具体是什么?

Parameters in calls to functions in PowerShell (all versions) are space-separated, not comma separated . PowerShell(所有版本)中对函数的调用中的参数以空格分隔,而不是逗号分隔 Also, the parentheses are entirely unneccessary and will cause a parse error in PowerShell 2.0 (or later) if Set-StrictMode -Version 2 or higher is active.此外,括号是完全不必要的,如果Set-StrictMode -Version 2或更高版本处于活动状态,则会在 PowerShell 2.0(或更高版本)中导致解析错误。 Parenthesised arguments are used in .NET methods only.带括号的参数仅用于 .NET 方法。

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

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

The correct answer has already been provided, but this issue seems prevalent enough to warrant some additional details for those wanting to understand the subtleties.已经提供了正确的答案,但这个问题似乎很普遍,足以为那些想要了解其中细微之处的人提供一些额外的细节。

I would have added this just as a comment, but I wanted to include an illustration--I tore this off my quick reference chart on PowerShell functions.我会添加这个作为评论,但我想包括一个插图——我把它从我关于 PowerShell 函数的快速参考图表上撕下来了。 This assumes function f's signature is f($a, $b, $c) :这假设函数 f 的签名是f($a, $b, $c)

函数调用的语法缺陷

Thus, one can call a function with space-separated positional parameters or order-independent named parameters.因此,可以使用空格分隔的位置参数或与顺序无关的命名参数调用函数。 The other pitfalls reveal that you need to be cognizant of commas, parentheses, and white space.其他陷阱表明您需要了解逗号、括号空格。

For further reading, see my article Down the Rabbit Hole: A Study in PowerShell Pipelines, Functions, and Parameters .如需进一步阅读,请参阅我的文章Down the Rabbit Hole: A Study in PowerShell Pipelines, Functions, and Parameters The article contains a link to the quick reference/wall chart as well.该文章还包含指向快速参考/挂图的链接。

There are some good answers here, but I wanted to point out a couple of other things.这里有一些很好的答案,但我想指出其他一些事情。 Function parameters are actually a place where PowerShell shines.函数参数其实是 PowerShell 大放异彩的地方。 For example, you can have either named or positional parameters in advanced functions like so:例如,您可以在高级函数中使用命名参数或位置参数,如下所示:

function Get-Something
{
    Param
    (
         [Parameter(Mandatory=$true, Position=0)]
         [string] $Name,
         [Parameter(Mandatory=$true, Position=1)]
         [int] $Id
    )
}

Then you could either call it by specifying the parameter name, or you could just use positional parameters, since you explicitly defined them.然后您可以通过指定参数名称来调用它,或者您可以只使用位置参数,因为您明确定义了它们。 So either of these would work:所以这些中的任何一个都可以工作:

Get-Something -Id 34 -Name "Blah"
Get-Something "Blah" 34

The first example works even though Name is provided second, because we explicitly used the parameter name.即使第二个提供了Name ,第一个示例仍然有效,因为我们明确使用了参数名称。 The second example works based on position though, so Name would need to be first.但是,第二个示例基于位置工作,因此Name必须是第一个。 When possible, I always try to define positions so both options are available.如果可能,我总是尝试定义职位,以便两个选项都可用。

PowerShell also has the ability to define parameter sets. PowerShell 还具有定义参数集的能力。 It uses this in place of method overloading, and again is quite useful:它使用它来代替方法重载,并且非常有用:

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
    )
}

Now the function will either take a name, or an id, but not both.现在该函数将采用名称或 id,但不能同时采用两者。 You can use them positionally, or by name.您可以按位置或按名称使用它们。 Since they are a different type, PowerShell will figure it out.由于它们是不同的类型,PowerShell 会弄清楚。 So all of these would work:所以所有这些都可以工作:

Get-Something "some name"
Get-Something 23
Get-Something -Name "some name"
Get-Something -Id 23

You can also assign additional parameters to the various parameter sets.您还可以将其他参数分配给各种参数集。 (That was a pretty basic example obviously.) Inside of the function, you can determine which parameter set was used with the $PsCmdlet.ParameterSetName property. (这显然是一个非常基本的示例。)在函数内部,您可以确定哪个参数集与 $PsCmdlet.ParameterSetName 属性一起使用。 For example:例如:

if($PsCmdlet.ParameterSetName -eq "Name")
{
    Write-Host "Doing something with name here"
}

Then, on a related side note, there is also parameter validation in PowerShell.然后,在相关的旁注中,PowerShell 中还有参数验证。 This is one of my favorite PowerShell features, and it makes the code inside your functions very clean.这是我最喜欢的 PowerShell 功能之一,它使函数内的代码非常干净。 There are numerous validations you can use.您可以使用许多验证。 A couple of examples are:几个例子是:

function Get-Something
{
    Param
    (
         [Parameter(Mandatory=$true, Position=0)]
         [ValidatePattern('^Some.*')]
         [string] $Name,
         [Parameter(Mandatory=$true, Position=1)]
         [ValidateRange(10,100)]
         [int] $Id
    )
}

In the first example, ValidatePattern accepts a regular expression that assures the supplied parameter matches what you're expecting.在第一个示例中,ValidatePattern 接受一个正则表达式,以确保提供的参数与您期望的相匹配。 If it doesn't, an intuitive exception is thrown, telling you exactly what is wrong.如果没有,就会抛出一个直观的异常,告诉你到底哪里出了问题。 So in that example, 'Something' would work fine, but 'Summer' wouldn't pass validation.所以在那个例子中,“Something”可以正常工作,但“Summer”不会通过验证。

ValidateRange ensures that the parameter value is in between the range you expect for an integer. ValidateRange 确保参数值在您期望的整数范围之间。 So 10 or 99 would work, but 101 would throw an exception.所以 10 或 99 会起作用,但 101 会抛出异常。

Another useful one is ValidateSet, which allows you to explicitly define an array of acceptable values.另一个有用的是 ValidateSet,它允许您显式定义一个可接受值的数组。 If something else is entered, an exception will be thrown.如果输入其他内容,将引发异常。 There are others as well, but probably the most useful one is ValidateScript.还有其他的,但可能最有用的一个是 ValidateScript。 This takes a script block that must evaluate to $true, so the sky is the limit.这需要一个必须评估为 $true 的脚本块,所以没有限制。 For example:例如:

function Get-Something
{
    Param
    (
         [Parameter(Mandatory=$true, Position=0)]
         [ValidateScript({ Test-Path $_ -PathType 'Leaf' })]
         [ValidateScript({ (Get-Item $_ | select -Expand Extension) -eq ".csv" })]
         [string] $Path
    )
}

In this example, we are assured not only that $Path exists, but that it is a file, (as opposed to a directory) and has a .csv extension.在此示例中,我们不仅可以确保 $Path 存在,而且可以确保它是一个文件(与目录相反)并且具有 .csv 扩展名。 ($_ refers to the parameter, when inside your scriptblock.) You can also pass in much larger, multi-line script blocks if that level is required, or use multiple scriptblocks like I did here. ($_ 指的是参数,当在您的脚本块中时。)如果需要该级别,您还可以传入更大的多行脚本块,或者像我在这里所做的那样使用多个脚本块。 It's extremely useful and makes for nice clean functions and intuitive exceptions.它非常有用,可以提供很好的干净功能和直观的异常。

You call PowerShell functions without the parentheses and without using the comma as a separator.您调用 PowerShell 函数时不带括号,也不使用逗号作为分隔符。 Try using:尝试使用:

test "ABC" "DEF"

In PowerShell the comma (,) is an array operator, eg在 PowerShell 中,逗号 (,) 是一个数组运算符,例如

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

It sets $a to an array with three values.它将$a设置为具有三个值的数组。

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

Test "ABC" "DEF"

If you're a C# / Java / C++ / Ruby / Python / Pick-A-Language-From-This-Century developer and you want to call your function with commas, because that's what you've always done, then you need something like this:如果您是 C# / Java / C++ / Ruby / Python / Pick-A-Language-From-This-Century 开发人员,并且您想用逗号调用您的函数,因为这是您一直在做的事情,那么您需要一些东西像这样:

$myModule = New-Module -ascustomobject { 
    function test($arg1, $arg2) { 
        echo "arg1 = $arg1, and arg2 = $arg2"
    }
}

Now call:现在调用:

$myModule.test("ABC", "DEF")

and you'll see你会看到

arg1 = ABC, and arg2 = DEF

If you don't know (or care) how many arguments you will be passing to the function, you could also use a very simple approach like;如果您不知道(或不关心)将传递给函数的参数数量,您也可以使用一种非常简单的方法,例如;

Code :代码

function FunctionName()
{
    Write-Host $args
}

That would print out all arguments.这将打印出所有论点。 For example:例如:

FunctionName a b c 1 2 3

Output输出

a b c 1 2 3

I find this particularly useful when creating functions that use external commands that could have many different (and optional) parameters, but relies on said command to provide feedback on syntax errors, etc.我发现这在创建使用可能具有许多不同(和可选)参数的外部命令的函数时特别有用,但依赖于所述命令来提供有关语法错误等的反馈。

Here is a another real-world example (creating a function to the tracert command, which I hate having to remember the truncated name);这是另一个现实世界的例子(为 tracert 命令创建一个函数,我讨厌必须记住截断的名称);

Code :代码

Function traceroute
{
    Start-Process -FilePath "$env:systemroot\system32\tracert.exe" -ArgumentList $args -NoNewWindow
}

Because this is a frequent viewed question, I want to mention that a PowerShell function should use approved verbs ( Verb-Noun as the function name).因为这是一个经常被查看的问题,所以我想提一下 PowerShell 函数应该使用认可的动词Verb-Noun作为函数名称)。 The verb part of the name identifies the action that the cmdlet performs.名称的动词部分标识 cmdlet 执行的操作。 The noun part of the name identifies the entity on which the action is performed.名称的名词部分标识对其执行操作的实体。 This rule simplifies the usage of your cmdlets for advanced PowerShell users.此规则为高级 PowerShell 用户简化了 cmdlet 的使用。

Also, you can specify things like whether the parameter is mandatory and the position of the parameter:此外,您可以指定参数是否为必填项以及参数的位置等内容:

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"
}

To pass the parameter to the function you can either use the position :要将参数传递给函数,您可以使用position

Test-Script "Hello" "World"

Or you specify the parameter name :或者您指定参数名称

Test-Script -arg1 "Hello" -arg2 "World"

You don't use parentheses like you do when you call a function within C#.不像在 C# 中调用函数时那样使用括号


I would recommend to always pass the parameter names when using more than one parameter, since this is more readable .我建议在使用多个参数时始终传递参数名称,因为这样更具可读性

If you try:如果你试试:

PS > Test("ABC", "GHI") ("DEF")

you get:你得到:

$arg1 value: ABC GHI
$arg2 value: DEF

So you see that the parentheses separates the parameters所以你看到括号分隔参数


If you try:如果你试试:

PS > $var = "C"
PS > Test ("AB" + $var) "DEF"

you get:你得到:

$arg1 value: ABC
$arg2 value: DEF

Now you could find some immediate usefulness of the parentheses - a space will not become a separator for the next parameter - instead you have an eval function.现在你可以发现括号的一些直接用途——空格不会成为下一个参数的分隔符——而是你有一个 eval 函数。

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

Test("ABC") ("DEF")

I don't know what you're doing with the function, but have a look at using the 'param' keyword.我不知道你在用这个函数做什么,但是看看使用 'param' 关键字。 It's quite a bit more powerful for passing parameters into a function, and makes it more user friendly.将参数传递给函数的功能要强大得多,并且更加用户友好。 Below is a link to an overly complex article from Microsoft about it.下面是微软关于它的一篇过于复杂的文章的链接。 It isn't as complicated as the article makes it sound.它并不像文章所说的那么复杂。

Param Usage 参数用法

Also, here is an example from a question on this site:另外,这是本网站上一个问题的示例:

Check it out.一探究竟。

I don't see it mentioned here, but splatting your arguments is a useful alternative and becomes especially useful if you are building out the arguments to a command dynamically (as opposed to using Invoke-Expression ).我没有看到这里提到它,但是splatting你的参数是一个有用的选择,如果你动态地构建命令的参数(而不是使用Invoke-Expression ),它变得特别有用。 You can splat with arrays for positional arguments and hashtables for named arguments.您可以为位置参数使用数组,为命名参数使用哈希表。 Here are some examples:这里有些例子:

Note: You can use positional splats with external commands arguments with relative ease, but named splats are less useful with external commands.注意:您可以相对轻松地将位置 splats 与外部命令参数一起使用,但命名 splats 对于外部命令的用处不大。 They work, but the program must accept arguments in the -Key:Value format as each parameter relates to the hashtable key/value pairs.它们可以工作,但程序必须接受-Key:Value格式的参数,因为每个参数都与哈希表键/值对相关。 One example of such software is the choco command from the Chocolatey package manager for Windows.此类软件的一个示例是用于 Windows 的 Chocolatey 包管理器中的choco命令。

Splat With Arrays (Positional Arguments) Splat with Arrays(位置参数)

Test-Connection with Positional Arguments带有位置参数的测试连接

Test-Connection www.google.com localhost

With Array Splatting使用阵列溅射

$argumentArray = 'www.google.com', 'localhost'
Test-Connection @argumentArray

Note that when splatting, we reference the splatted variable with an @ instead of a $ .请注意,在 splatting 时,我们使用@而不是$来引用 splatted 变量。 It is the same when using a Hashtable to splat as well.使用 Hashtable 进行 splat 时也是如此。

Splat With Hashtable (Named Arguments) Splat with Hashtable(命名参数)

Test-Connection with Named Arguments使用命名参数的测试连接

Test-Connection -ComputerName www.google.com -Source localhost

With Hashtable Splatting使用散列表飞溅

$argumentHash = @{
  ComputerName = 'www.google.com'
  Source = 'localhost'
}
Test-Connection @argumentHash

Splat Positional and Named Arguments Simultaneously Splat 位置和命名参数同时

Test-Connection With Both Positional and Named Arguments位置参数和命名参数的测试连接

Test-Connection www.google.com localhost -Count 1

Splatting Array and Hashtables Together将数组和散列表放在一起

$argumentHash = @{
  Count = 1
}
$argumentArray = 'www.google.com', 'localhost'
Test-Connection @argumentHash @argumentArray

I stated the following earlier:我之前说过以下几点:

The common problem is using the singular form $arg , which is incorrect.常见的问题是使用单数形式$arg ,这是不正确的。 It should always be plural as $args .它应该始终是复数$args

The problem is not that.问题不在于。 In fact, $arg can be anything else.事实上, $arg可以是其他任何东西。 The problem was the use of the comma and the parentheses.问题是逗号和括号的使用。

I run the following code that worked and the output follows:我运行以下有效的代码,输出如下:

Code:代码:

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

Test "ABC" "DEF"测试“ABC”“DEF”

Output:输出:

$var1 value: ABC
$var2 value: DEF
Function Test {
    Param([string]$arg1, [string]$arg2)

    Write-Host $arg1
    Write-Host $arg2
}

This is a proper params declaration.这是一个正确的params声明。

See about_Functions_Advanced_Parameters .请参阅about_Functions_Advanced_Parameters

And it indeed works.它确实有效。

You can pass parameters in a function like this also:您也可以在这样的函数中传递参数

function FunctionName()
{
    Param ([string]$ParamName);
    # Operations
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何将多个字符串参数传递给PowerShell脚本? - How do I pass multiple string parameters to a PowerShell script? PowerShell如何在函数中传递多个整数参数 - PowerShell How to Pass multiple integer parameters in a function 如何在Powershell中的函数中传递多个参数? - How to pass multiple parameters in a function in Powershell? 如何将多个变量传递给 powershell 函数? - How do I pass multiple variables to a powershell function? 如何将 SwitchParameter 传递给 Powershell 中的 function? - How do I pass a SwitchParameter to a function in Powershell? 如何在 powershell 函数中传递参数? - How can I pass-through parameters in a powershell function? 如何从 PowerShell 正确地将参数传递给 ImageMagick? - How do I correctly pass parameters to ImageMagick from PowerShell? 如何将参数传递给此 PowerShell 脚本中的批处理文件? - How do I pass parameters to the batch file in this PowerShell script? 如何在Powershell中的函数中获得命名但未声明的参数? - How do I get named but undeclared parameters in a function in Powershell? Powershell:在命令行调用powershell时,如何将变量传递给切换参数? - Powershell: How do I pass variables to switch parameters when invoking powershell at the command line?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM