powershell 如何有效地测试.PS1脚本是函数的“模块”还是普通脚本?

i5desfxk  于 2023-04-12  发布在  Shell
关注(0)|答案(1)|浏览(139)

我的组织有大量的PowerShell脚本。其中一些是处理逻辑/执行某些操作的直接脚本,但其他脚本本质上是“模块”(但不是 * 实际 * 模块),因为它们只包含我们使用的常见功能,这些功能由其他脚本导入和使用。
我试图找出一种方法来确定.PS1文件是一个“脚本”,还是一个“模块”,因为它只包含函数,不处理任何逻辑。
我的想法是我只捕获脚本的内容,看看它是否只包含一个或多个:function X { * },没有其他的。可能使用正则表达式来匹配该模式。
但这看起来很混乱,所以我想知道是否有人有任何想法,我如何能做得更好?
我知道我可能会让一些人推荐我们以PowerShell的方式构建模块,但这些都是已经开发的预先存在的脚本,我当然没有权力告诉我的整个组织改变他们编写脚本的方式。

qmelpv7a

qmelpv7a1#

我的想法是我只捕获脚本的内容,看看它是否只包含一个或多个:函数X { * },除此之外什么都没有。
真是个好计划!
[...]可能使用正则表达式来匹配该模式。
这计划太烂了!
使用PowerShell自己的解析器来解析现有脚本,而不是regex:

using namespace System.Management.Automation.Language

# start by enumerating all the script files in scope
$results = Get-ChildItem folder\with\script\files -Filter *.ps1 -Recurse |ForEach-Object {
  # construct an object that will hold the output for each file analyzed
  $result = [pscustomobject]@{
    Name          = $_.Name
    Path          = $_.FullName
    FunctionCount = 0
    PipelineCount = 0
    OtherCount    = 0
    HadErrors     = $false
  }

  try {
    # attempt to parse the script file
    $scriptAst = [Parser]::ParseFile($_.FullName, [ref]$null, [ref]$null)

    # inspect the top-level statements in the resulting AST, capture the counts of particularly interesting syntax elements
    $result.FunctionCount = $scriptAst.EndBlock.Statements.Where({$_ -is [FunctionDefinitionAst]}).Count
    $result.PipelineCount = $scriptAst.EndBlock.Statements.Where({$_ -is [PipelineAst]}).Count
    $result.OtherCount    = $scriptAst.EndBlock.Statements.Where({$_ -isnot [PipelineAst] -and $_ -isnot [FunctionDefinitionAst]}).Count
  }
  catch {
    # in case of failure we want to report that to the caller
    $result.HadErrors = $true
  }

  # output the details captured
  $result
}

现在我们已经分析了所有脚本中的顶级语句,我们可以开始根据大多数可能是“模块式”的期望来过滤它们:

$results |Where-Object { $_.FunctionCount -gt 0 -and $_.PipelineCount -eq 0 } |ForEach-Object {
    Write-Host "Script at '$($_.Path)' looks like a module! No pipelines, just functions!"
}

相关问题