如何在CmdletBinding()脚本中定义函数?

moj*_*ojo 3 powershell pipeline function cmdlet

我正在编写一个脚本,我想使用PowerShell的CmdletBinding().有没有办法在脚本中定义函数?当我尝试时,PowerShell在表达式或语句中抱怨"意外的toke'函数"

这是我正在尝试做的简化示例.

[CmdletBinding()]
param(
    [String]
    $Value
)

BEGIN {
    f("Begin")
}

PROCESS {
    f("Process:" + $Value)
}

END {
    f("End")
}

Function f() {
    param([String]$m)
    Write-Host $m
}
Run Code Online (Sandbox Code Playgroud)

在我的情况下,编写模块是浪费的开销.这些函数只需要可用于这一个脚本.我不想弄乱模块路径或脚本位置.我只想运行一个包含其中定义的函数的脚本.

Ans*_*ers 7

当代码应该处理管道输入时,您使用begin,processend阻止.该begin块用于预处理,并在输入处理开始之前运行一次.该end块用于后处理,并在完成输入处理后运行一次.如果你想在end块之外的任何地方调用一个函数,你可以在块中定义它(在begin块中反复重新定义它将process浪费资源,即使你没有在begin块中使用它).

[CmdletBinding()]
param(
    [String]$Value
)

BEGIN {
    Function f() {
        param([String]$m)
        Write-Host $m
    }

    f("Begin")
}

PROCESS {
    f("Process:" + $Value)
}

END {
    f("End")
}
Run Code Online (Sandbox Code Playgroud)

引用自about_Functions:

将对象管道化为函数

任何函数都可以从管道获取输入.您可以使用Begin,Process和End关键字控制函数如何处理来自管道的输入.以下示例语法显示了三个关键字:

function <name> { 
    begin {<statement list>}
    process {<statement list>}
    end {<statement list>}
}
Run Code Online (Sandbox Code Playgroud)

Begin语句列表仅在函数开头运行一次.

Process语句列表为管道中的每个对象运行一次.当Process块正在运行时,每个管道对象都被分配给$ _自动变量,一次一个管道对象.

函数收到管道中的所有对象后,End语句列表运行一次.如果没有使用Begin,Process或End关键字,则所有语句都被视为End语句列表.


如果您的代码不处理管道输入,你可以放下begin,process以及end完全块,并把一切都在脚本主体:

[CmdletBinding()]
param(
    [String]$Value
)

Function f() {
    param([String]$m)
    Write-Host $m
}

f("Begin")
f("Process:" + $Value)
f("End")
Run Code Online (Sandbox Code Playgroud)

编辑:如果要将f脚本末尾的定义放在脚本末尾,则需要将其余代码定义为worker/main/whatever函数,并在脚本末尾调用该函数,例如:

[CmdletBinding()]
param(
    [String]$Value
)

function Main {
    [CmdletBinding()]
    param(
        [String]$Param
    )

    BEGIN   { f("Begin") }
    PROCESS { f("Process:" + $Param) }
    END     { f("End") }
}

Function f() {
    param([String]$m)
    Write-Host $m
}

Main $Value
Run Code Online (Sandbox Code Playgroud)