PowerShell AST FindAll方法使用$ args [0]获取一个scriptblock

时间:2015-09-22 18:22:06

标签: powershell abstract-syntax-tree

我一直在使用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方法时,如何将任何参数实际传递到scriptblock中?

2 个答案:

答案 0 :(得分:2)

FindAll方法具有以下签名(来自msdn):

public IEnumerable<Ast> FindAll (
    Func<Ast,bool> predicate,
    bool searchNestedScriptBlocks
)

因此,第一个参数是一个以Ast作为输入的委托,并返回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>
    }
}

答案 1 :(得分:1)

将scriptblock视为匿名回调函数。

使用Where-Object { $someCondition }时会发生同样的事情。

.FindAll找到所有(事物),并为每个人调用你提供的功能。它显然期望得到[bool]结果,并返回满足回调中存在条件的对象。

在powershell中的函数或脚本或脚本块中,您可以使用明确定义的命名参数,也可以reference parameters without declaring them using the $args array,这是这里发生的事情。

使用scriptblock作为回调类似于将其用于事件:

  

$参数数量

   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.