在powershell中,在函数中包含参数或在函数中放置参数有区别吗?

Nic*_*oru 5 powershell

在powershell中,您可以使用以下方法创建函数function name {commands}并使这些函数接受参数:

function myFunction {
    param($var1, $var2)
}
Run Code Online (Sandbox Code Playgroud)

但你也可以用

function myFunction($var1, $var2) {}
Run Code Online (Sandbox Code Playgroud)

他们会是一样的。

例如,如果我创建了一个函数func1

function func1 {
    param($var1, $var2)
    echo "$var1 $var2"
}
Run Code Online (Sandbox Code Playgroud)

我会通过使用func1 1 2where $var1will be equal to1$var2will be equal to 来调用它2

输入:

PS C:\Users\Neko> func1 1 2
Run Code Online (Sandbox Code Playgroud)

输出:

1 2
Run Code Online (Sandbox Code Playgroud)

但是,如果我做同样的事情,而是使用另一种将参数传递给函数的方法:

function func2($var1, $var2) {
    echo "$var1 $var2"
}
Run Code Online (Sandbox Code Playgroud)

我也会以完全相同的方式调用它,通过使用func2 1 2where$var1将等于1$var2等于2前一个函数来调用它。

输入:

PS C:\Users\Neko> func2 1 2
Run Code Online (Sandbox Code Playgroud)

输出:

1 2
Run Code Online (Sandbox Code Playgroud)

因此,函数的两个再现之间的一切似乎都相同且不变,所以我的问题是,将参数传递给函数的两种方法之间是否存在差异,或者它们实际上是否相同?即使它是最细微的细节,或者只是解析差异,我也想知道两者在功能上的任何差异,因为 param 也有其他用途。

UPDATE:的参数,你可以在做param喜欢[parameter(Mandatory=$true, ValueFromPipeline=$true)][String[]]是不是唯一的PARAM。您还可以通过执行以下操作在另一个“非参数”示例中完成此操作:

function func2(
    [parameter(Mandatory=$true, ValueFromPipeline=$true, etc)] 
    [String[]]
    $var1, $var2
) {
    echo "$var1 $var2" 
}
Run Code Online (Sandbox Code Playgroud)

mkl*_*nt0 6

为了补充7cc 的有用答案

虽然在定义函数的参数时这两种语法形式大多可以互换,但只有块语法在以下情况下有效param(...)

  • 如果您想使用[CmdletBinding()]属性使您的函数或脚本成为高级函数或脚本。[1]

  • 如果您正在编写脚本文件( *.ps1) 或脚本块( { ... }):为它们声明参数的唯一方法是param(...)在开头放置一个块。

因此,您可以选择始终使用param(...)块语法,以确保函数和脚本参数定义之间的一致性

如果使用[CmdletBinding(...)]) 属性,它必须直接位于param(...)块之前。


至于:

我会用 func1(1)(2)

不,你会这样称呼它:

func1 1 2
Run Code Online (Sandbox Code Playgroud)

也就是说,PowerShell 函数的调用方式类似于shell 命令:不带括号,以空格分隔;虽然您的调用恰好也有效,但使用(...)围绕参数可以改变它们的解释:

  • 没有封闭(...)的参数在参数模式下被解析,其中,值得注意的是,字符串不需要被引用

  • 封闭的(...), 在表达式模式下解析,其中字符串确实需要引用。

有关更多信息,请参阅此答案


[1] 虽然您可以将[CmdletBinding(...)]属性放在带有function Foo (...) { ... }语法的括号内而不会引起错误,但这样做实际上被忽略了。另外,在没有(有效的)显式 [CmdletBinding(...)]属性的情况下,无论使用哪种语法,如果您碰巧用[Parameter()]属性装饰至少一个参数,您将获得高级函数的默认行为(例如,支持自动通用参数,例如-Verbose) ,因为使用[Parameter()] 隐式使函数成为高级函数(就像一个[CmdletBinding()]属性 - 没有显式属性值 - 有效)。但是,如果您需要显式[CmdletBinding(...)]属性,以便选择非默认高级功能行为,通过属性值,例如PositionalBinding=$falseor SupportsShouldProcess=$true,使用param(...)块是您唯一的选择。


7cc*_*7cc 5

一件事是该CmdletBinding属性需要Param

function Echo-Confirm
{
    # Here
    [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    Param ($val=1)

    if ($PSCmdlet.ShouldProcess($val) -eq $true) {
        Write-Output "Confirmed $val"
    }
}
Run Code Online (Sandbox Code Playgroud)

此评论后编辑

语法很好,但CmdletBinding没有效果

Function foo (
    [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    [Parameter()]$val=1
) {
    # never confirm
    if ($PSCmdlet.ShouldProcess($val) -eq $true) {
        Write-Output "always here"
    }
    else {
       Write-Output "never here"
    }
}


foo -Confirm
# throws an error
foo: A parameter cannot be found that matches parameter name 'confirm'.
Run Code Online (Sandbox Code Playgroud)