使用 AST 解析 PowerShell 脚本
Parsing PowerShell script with AST
我正在尝试通过 Pester 脚本进行解析并从 -Tag
参数中提取值。任何人都知道如何使用 [System.Management.Automation.PSParser]
来做到这一点?我在想我必须循环遍历 [System.Management.Automation.PSParser]::Tokenize()
编辑的标记 return 但这看起来很笨拙并且考虑到 -Tag
的值可以以多种不同的格式给出,不太实用
归根结底,我希望 return 一个带有 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]
是正确的方法还是有更好的方法?
干杯
使用 PS3.0+ Language namespace AST 解析器:
$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 中的调试器检查各种数据类型情况。
我正在尝试通过 Pester 脚本进行解析并从 -Tag
参数中提取值。任何人都知道如何使用 [System.Management.Automation.PSParser]
来做到这一点?我在想我必须循环遍历 [System.Management.Automation.PSParser]::Tokenize()
编辑的标记 return 但这看起来很笨拙并且考虑到 -Tag
的值可以以多种不同的格式给出,不太实用
归根结底,我希望 return 一个带有 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]
是正确的方法还是有更好的方法?
干杯
使用 PS3.0+ Language namespace AST 解析器:
$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 中的调试器检查各种数据类型情况。