我正在对某些PowerShell数据集进行规范化,一个处理步骤是将所有变量替换为X,并将所有字符串文字替换为Y,以便我可以检测和删除几乎重复的副本。
但是,我注意到对于规范化后的许多脚本,整个脚本可以归结为很多Y和一些X,几乎没有其他任何代码。这不是我所期望的,因为脚本中只有少数变量和字符串文字。
要查找所有字符串文字,我使用了以下命令:
$Strings = $AST.FindAll({$args[0] -is System.Management.Automation.Language.StringConstantExpressionAst]}, $true)
为解决此问题,我使用ShowPSAst (PowerShell AST visualization tool)可视化了一个示例脚本,其中上述问题很明显。
原始脚本如下:
Describe "Files" -Tag OSX,Linux {
It "is utf-8 encoded" {
$true | Should Be $false
}
It "uses Unix-style line endings" {
$true | Should Be $false
}
It "has a shebang" {
$true | Should Be $false
}
}
Describe "Placeholder for Nano tests" -Tag Nano {
}
规范化后,我得到以下信息:
Y Y -Tag Y,Y {
Y Y {
X | Y Y X
}
Y Y {
X | Y Y X
}
Y Y {
X | Y Y X
}
}
Y Y -Tag Y {
}
上述脚本的AST可视化摘录:
请注意,图像右面板中突出显示的部分与左面板中的AST节点CommandAST
相对应,然后,AST节点StringConstantExpressionAst
作为子节点。看看这些AST节点,就可以理解为什么我的规范版本中有那么多Y。但是,令我感到困惑的是,为什么突出显示的代码中几乎所有的单独标记都被视为StringContantExpressionAst
。我希望只有"Placeholder for Nano tests"
被视为字符串文字。
准确地说,我希望
Describe "Placeholder for Nano tests" -Tag Nano
要转化为
Describe Y -Tag Nano
而不是
Y Y -Tag Y
我并不是真正地独自使用PowerShell,也不知道它的复杂性,因此如果我缺少基本的东西,我深表歉意,在此感谢我对理解PowerShell行为的任何帮助。
答案 0 :(得分:1)
PowerShell是一种解释型语言,这意味着它在运行代码之前不会在代码的某些部分附加含义。在您的情况下,它不知道单词“ Describe”是指Pester模块中的Describe函数(它可能甚至没有导入到您的会话中),它同样意味着一个名为“ Describe”的外部程序。 exe”。
解析器所做的全部工作就是将命令的名称记为StringConstantExpressionAst
,这取决于运行时逻辑来查找要运行的具有该名称的东西。
如果仔细查看AST,您会发现“描述”令牌的StringConstantType
属性为BareWord
,而"my tests"
字符串的值为{{1} }。如果只想对“文字字符串”进行处理,则可以使用DoubleQuoted
属性作为过滤器。
StringConstantType
除了然后,您可能会错过诸如此类的未加引号的字符串:
$Strings = $AST.FindAll(
{
( $args[0] -is [System.Management.Automation.Language.StringConstantExpressionAst] ) -and
( $args[0].StringConstantType -ne "BareWord" )
},
$true
)
所以另一个更好的选择是忽略任何CommandAst节点中的第一个子元素。