PowerShell AST FindAll 方法采用带有 $args[0] 的脚本块
PowerShell AST FindAll method take a scriptblock with $args[0]
我一直在使用 PowerShell AST 为 PSScriptAnalyzer 创建一些自定义规则。
在很多AST的示例代码中,有一行我没看懂。这是一个例子。
首先解析一个文件,在本例中是 ISE 中当前打开的文件。
$AbstractSyntaxTree = [System.Management.Automation.Language.Parser]::
ParseInput($psISE.CurrentFile.Editor.Text, [ref]$null, [ref]$null)
到目前为止这是有道理的。假设我们要查找所有 ParameterAst 对象。下面是我看到的执行此操作的代码。
$params = $AbstractSyntaxTree.FindAll({$args[0] -is [System.Management.Automation.Language.ParameterAst]}, $true)
这行代码正在调用 FindAll
并传入一个脚本块,它似乎充当过滤器,因此只返回 ParameterAst 对象。
这里我不明白的是 $args[0]
如何适应这个调用。当调用 FindAll
方法时,任何参数实际上是如何传递到脚本块中的?
将脚本块视为匿名回调函数。
这和你使用 Where-Object { $someCondition }
时发生的事情是一样的。
.FindAll
找到所有的(事物)并且对于每一个它调用你提供的函数。它显然期待 [bool]
结果,并返回满足回调中存在的条件的对象。
在 powershell 的函数或脚本或脚本块中,您可以具有显式定义的命名参数,或者您可以 reference parameters without declaring them using the $args
array,这就是此处发生的情况。
将脚本块用作回调类似于将其用于事件:
$Args
Contains an array of the undeclared parameters and/or parameter
values that are passed to a function, script, or script block.
When you create a function, you can declare the parameters by using the
param keyword or by adding a comma-separated list of parameters in
parentheses after the function name.
In an event action, the $Args variable contains objects that represent
the event arguments of the event that is being processed.
FindAll
方法具有以下签名(来自 msdn):
public IEnumerable<Ast> FindAll (
Func<Ast,bool> predicate,
bool searchNestedScriptBlocks
)
所以第一个参数是一个委托,它将 Ast 作为输入,returns bool。
在 Powershell 中,您可以像这样创建这样的委托:
$delegate = { param($ast) $ast -is [System.Management.Automation.Language.ParameterAst] }
或不声明参数:
$delegate = { $args[0] -is [System.Management.Automation.Language.ParameterAst] }
FindAll
方法将执行类似的操作(伪代码):
foreach ($node in $allNodes) {
$shouldAdd = & $delegate $node <-- this is how $node gets passed to your delegate
if ($shouldAdd) {
<add the node to the output list>
}
}
我一直在使用 PowerShell AST 为 PSScriptAnalyzer 创建一些自定义规则。
在很多AST的示例代码中,有一行我没看懂。这是一个例子。
首先解析一个文件,在本例中是 ISE 中当前打开的文件。
$AbstractSyntaxTree = [System.Management.Automation.Language.Parser]::
ParseInput($psISE.CurrentFile.Editor.Text, [ref]$null, [ref]$null)
到目前为止这是有道理的。假设我们要查找所有 ParameterAst 对象。下面是我看到的执行此操作的代码。
$params = $AbstractSyntaxTree.FindAll({$args[0] -is [System.Management.Automation.Language.ParameterAst]}, $true)
这行代码正在调用 FindAll
并传入一个脚本块,它似乎充当过滤器,因此只返回 ParameterAst 对象。
这里我不明白的是 $args[0]
如何适应这个调用。当调用 FindAll
方法时,任何参数实际上是如何传递到脚本块中的?
将脚本块视为匿名回调函数。
这和你使用 Where-Object { $someCondition }
时发生的事情是一样的。
.FindAll
找到所有的(事物)并且对于每一个它调用你提供的函数。它显然期待 [bool]
结果,并返回满足回调中存在的条件的对象。
在 powershell 的函数或脚本或脚本块中,您可以具有显式定义的命名参数,或者您可以 reference parameters without declaring them using the $args
array,这就是此处发生的情况。
将脚本块用作回调类似于将其用于事件:
$Args
Contains an array of the undeclared parameters and/or parameter values that are passed to a function, script, or script block. When you create a function, you can declare the parameters by using the param keyword or by adding a comma-separated list of parameters in parentheses after the function name. In an event action, the $Args variable contains objects that represent the event arguments of the event that is being processed.
FindAll
方法具有以下签名(来自 msdn):
public IEnumerable<Ast> FindAll (
Func<Ast,bool> predicate,
bool searchNestedScriptBlocks
)
所以第一个参数是一个委托,它将 Ast 作为输入,returns bool。 在 Powershell 中,您可以像这样创建这样的委托:
$delegate = { param($ast) $ast -is [System.Management.Automation.Language.ParameterAst] }
或不声明参数:
$delegate = { $args[0] -is [System.Management.Automation.Language.ParameterAst] }
FindAll
方法将执行类似的操作(伪代码):
foreach ($node in $allNodes) {
$shouldAdd = & $delegate $node <-- this is how $node gets passed to your delegate
if ($shouldAdd) {
<add the node to the output list>
}
}