为什么这个 PowerShell 脚本中有这么多 StringConstantExpressionAst?
Why are there so many StringConstantExpressionAst's in this PowerShell script?
我正在对某些 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
,然后有很多 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 行为的任何帮助。
PowerShell 是一种解释型语言,这意味着在您 运行 之前,它不会为代码的某些部分赋予意义。在你的例子中,它不知道 "Describe" 这个词指的是 Pester 模块中的 Describe 函数(它甚至可能还没有导入到你的会话中),它同样可能意味着一个名为 "Describe.exe" 例如。
解析器所做的只是将命令的名称记录为 StringConstantExpressionAst
,然后由 运行时间逻辑来寻找 运行 的内容有那个名字。
如果您仔细查看您的 AST,您会发现 "Describe" 标记具有 BareWord
的 StringConstantType
属性 而 "my tests"
字符串值为 DoubleQuoted
。如果您只想对 "literal strings" 进行处理,您可以使用 StringConstantType
属性 作为过滤器。
$Strings = $AST.FindAll(
{
( $args[0] -is [System.Management.Automation.Language.StringConstantExpressionAst] ) -and
( $args[0].StringConstantType -ne "BareWord" )
},
$true
)
除了 然后 你可能会错过像这样的未加引号的字符串:
Describe Files -Tag OSX,Linux {
所以另一个(更好的?)选项可能是忽略任何 CommandAst 节点中的第一个子元素。
我正在对某些 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
,然后有很多 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 行为的任何帮助。
PowerShell 是一种解释型语言,这意味着在您 运行 之前,它不会为代码的某些部分赋予意义。在你的例子中,它不知道 "Describe" 这个词指的是 Pester 模块中的 Describe 函数(它甚至可能还没有导入到你的会话中),它同样可能意味着一个名为 "Describe.exe" 例如。
解析器所做的只是将命令的名称记录为 StringConstantExpressionAst
,然后由 运行时间逻辑来寻找 运行 的内容有那个名字。
如果您仔细查看您的 AST,您会发现 "Describe" 标记具有 BareWord
的 StringConstantType
属性 而 "my tests"
字符串值为 DoubleQuoted
。如果您只想对 "literal strings" 进行处理,您可以使用 StringConstantType
属性 作为过滤器。
$Strings = $AST.FindAll(
{
( $args[0] -is [System.Management.Automation.Language.StringConstantExpressionAst] ) -and
( $args[0].StringConstantType -ne "BareWord" )
},
$true
)
除了 然后 你可能会错过像这样的未加引号的字符串:
Describe Files -Tag OSX,Linux {
所以另一个(更好的?)选项可能是忽略任何 CommandAst 节点中的第一个子元素。