【问题标题】:Parsing PowerShell script with AST使用 AST 解析 PowerShell 脚本
【发布时间】:2016-10-07 03:45:03
【问题描述】:

我正在尝试解析 Pester 脚本并从 -Tag 参数中提取值。任何人都知道如何使用[System.Management.Automation.PSParser]?。我在想我必须遍历从 [System.Management.Automation.PSParser]::Tokenize() 返回的令牌,但这看起来很笨拙,并且考虑到 -Tag 的值可以以许多不同的格式给出,不是很实用。

最后,我希望返回一个带有 Describe 块名称的集合,以及该块的标签列表(如果有的话)。

Name     Tags        
----     ----        
Section1 {tag1, tag2}
Section2 {foo, bar}  
Section3 {asdf}      
Section4 {}      

这是我正在使用的 Pester 测试示例。

describe 'Section1' -Tag @('tag1', 'tag2') {
    it 'blah1' {
        $true | should be $true
    }
}
describe 'Section2' -Tag 'foo', 'bar' {
    it 'blah2' {
        $true | should be $true
    }    
}
describe 'Section3' -Tag 'asdf'{
    it 'blah3' {
        $true | should be $true
    }
}
describe 'Section4' {
   it 'blah4' {
        $true | should be $true
   }
}

有人对如何解决这个问题有任何想法吗? [System.Management.Automation.PSParser] 是正确的方法还是有更好的方法?

干杯

【问题讨论】:

    标签: powershell parsing abstract-syntax-tree


    【解决方案1】:

    使用 PS3.0+ Language namespaceAST 解析器:

    $text = Get-Content 'pester-script.ps1' -Raw # text is a multiline string, not an array!
    
    $tokens = $null
    $errors = $null
    [Management.Automation.Language.Parser]::ParseInput($text, [ref]$tokens, [ref]$errors).
        FindAll([Func[Management.Automation.Language.Ast,bool]]{
            param ($ast)
            $ast.CommandElements -and
            $ast.CommandElements[0].Value -eq 'describe'
        }, $true) |
        ForEach {
            $CE = $_.CommandElements
            $secondString = ($CE | Where { $_.StaticType.name -eq 'string' })[1]
            $tagIdx = $CE.IndexOf(($CE | Where ParameterName -eq 'Tag')) + 1
            $tags = if ($tagIdx -and $tagIdx -lt $CE.Count) {
                $CE[$tagIdx].Extent
            }
            New-Object PSCustomObject -Property @{
                Name = $secondString
                Tags = $tags
            }
        }
    
    Name       Tags             
    ----       ----             
    'Section1' @('tag1', 'tag2')
    'Section2' 'foo', 'bar'     
    'Section3' 'asdf'           
    'Section4' 
    

    代码不会将标签解释为字符串列表,而只是使用原始文本extent
    使用 PowerShell ISE / Visual Studio / VSCode 中的调试器检查各种数据类型案例。

    【讨论】:

    • 谢谢@w0xx0m。稍作修改,我就可以将标签作为 [string] 或 [string[]] 拉出。
    猜你喜欢
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 2020-06-30
    • 2018-12-30
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多