将匿名多行函数作为参数传递给另一个函数

时间:2013-12-29 15:14:31

标签: powershell

假设有一个函数将两个函数作为参数:

function do_until([scriptblock] $f, [scriptblock] $p, [System.TimeSpan] $timeout = (New-Timespan -Minutes 5), [System.TimeSpan] $delay = (New-Timespan -Seconds 5))
{
    $timer = [diagnostics.stopwatch]::StartNew()
    do
    {
        $f.Invoke()
        Start-Sleep $delay.Seconds
    } until ($p.Invoke() -or $timer.elapsed -ge $timeout)
}

这有效:

do_until { "hi!" } { 1 -gt 2 } (New-Timespan -Seconds 10) (New-Timespan -Seconds 1)

这失败

do_until 
{ 
    "hi!" 
    "and again!"
} { 1 -gt 2 } (New-Timespan -Seconds 10) (New-Timespan -Seconds 1)

有错误

At C:\c\powershell\functions.ps1:15 char:3
+ } { 1 -gt 2 } (New-Timespan -Seconds 10) (New-Timespan -Seconds 1)
+   ~
Unexpected token '{' in expression or statement.
At C:\c\powershell\functions.ps1:15 char:15
+ } { 1 -gt 2 } (New-Timespan -Seconds 10) (New-Timespan -Seconds 1)
+               ~
Unexpected token '(' in expression or statement.
At C:\c\powershell\functions.ps1:15 char:42
+ } { 1 -gt 2 } (New-Timespan -Seconds 10) (New-Timespan -Seconds 1)
+                                          ~
Unexpected token '(' in expression or statement.
    + CategoryInfo          : ParserError: (:) [], ParseException
    + FullyQualifiedErrorId : UnexpectedToken

如何将此匿名多行函数作为参数传递给do_until

2 个答案:

答案 0 :(得分:4)

PowerShell将do_until解释为一个完整的命令。代替:

1)在与函数调用相同的行上启动scriptblock(开头{不会形成完整的表达式,因此PowerShell将继续解析为以下行)。

do_until {
  "hi!"
  "and again!"
} { 1 -gt 2 } (New-Timespan -Seconds 10) (New-Timespan -Seconds 1)

2)使用`转义字符通知PowerShell有关多行命令的信息。

do_until `
{
  "hi!"
  "and again!"
} { 1 -gt 2 } (New-Timespan -Seconds 10) (New-Timespan -Seconds 1)

3)在调用函数之前将scriptblock保存到变量中(如开放{,PowerShell将在不完整的=赋值后继续解析。)

$action =
{
  "hi!"
  "and again!"
}

do_until $action { 1 -gt 2 } (New-Timespan -Seconds 10) (New-Timespan -Seconds 1)

答案 1 :(得分:2)

有两种选择:

1)使用行继续符``(反引号),例如:

do_until `
{ 
    "hi!" 
    "and again!"
} { 1 -gt 2 } (New-Timespan -Seconds 10) (New-Timespan -Seconds 1)

2)不要将开口花括号放在它自己的行上,例如:

do_until { 
    "hi!" 
    "and again!"
} { 1 -gt 2 } (New-Timespan -Seconds 10) (New-Timespan -Seconds 1)

我更喜欢第二个选项,因为有时很难看到反引号。