当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 使用 PowerShell AST 发现别名

作者:精品下载站 日期:2024-12-14 08:05:03 浏览:16 分类:玩电脑

使用 PowerShell AST 发现别名


我一直在开发一个新的 PowerShell 模块,该模块包含我最近关于将 PowerShell 脚本和函数转换为文件的一些帖子中的代码。我什至编写了一个脚本,将其视为元脚本,以使用我添加到模块中的命令来创建模块。我改天再讲。在编写此脚本的过程中,我意识到我还想识别文件中定义的函数的别名。

具体来说,我想找到函数本身定义的别名。

Function Get-Foo {
  [cmdletbinding()]
  [alias("gf")]
  Param (...)
...

我可以简单地对脚本文件进行点源搜索,然后查找别名。但我不想假设点源是一种选择。相反,我返回使用 AST 解析文件。

不幸的是,我在 AST 中找不到任何专门检索命令别名的内容。如果我遗漏了什么,请告诉我。相反,我依靠正则表达式来解析函数体。使用我在之前的文章中展示的代码,现在在文件中查找函数很简单。

[玩转系统] 使用 PowerShell AST 发现别名

这只是一个概念验证。我仍然需要提取别名。我将使用使用前瞻和后瞻的正则表达式模式。

[regex]$rx = "(?<=alias\().*(?=\)\])"

该表达式表示使用 .* 匹配任何内容,其中前面(lookbehind)的文本是“alias(”,后面(lookahead)的文本是“)]”。括号和方括号是正则表达式字符,因此我需要用斜杠将它们转义。然后我可以清理匹配并获取别名。

这是我的 PowerShell 函数。

Function Get-FunctionAlias {
    [cmdletbinding()]
    [alias("gfal", "ga")]
    [outputType("string")]
    Param(
        [Parameter(Position = 0, Mandatory, HelpMessage = "Specify the .ps1 or .psm1 file with defined functions.")]
        [ValidateScript( {
            If (Test-Path $_ ) {
                $True
            }
            Else {
                Throw "Can't validate that $_ exists. Please verify and try again."
                $False
            }
        })]
        [ValidateScript( {
            If ($_ -match "\.ps(m)?1$") {
                $True
            }
            Else {
                Throw "The path must be to a .ps1 or .psm1 file."
                $False
            }
        })]
        [string]$Path
    )

    New-Variable astTokens -Force
    New-Variable astErr -Force
    $Path = Convert-Path -Path $path
    [regex]$rx = "(?<=alias\().*(?=\)\])"
    Write-Verbose "Parsing $path for functions."
    $AST = [System.Management.Automation.Language.Parser]::ParseFile($Path, [ref]$astTokens, [ref]$astErr)

    #parse out functions using the AST
    $functions = $ast.FindAll( { $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] }, $true)
    if ($functions.count -gt 0) {
        foreach ($f in $functions) {
            if ($rx.IsMatch($f.body)) {
                [pscustomobject]@{
                    Name  = $f.name
                    #remove quotes from the alias names and join as a comma-separated array
                    Alias = ($rx.matches($f.body).value -replace """|'", "") -split ","
                }
            }
        }
    }
}

让我们使用该函数来发现它自己的别名。

[玩转系统] 使用 PowerShell AST 发现别名

我的 PowerShell 脚本文件有两个定义了别名的函数。我可以在编写新 PowerShell 模块的构建脚本时使用此信息。该主题是议程上的下一个主题。

同时,我希望您能尝试一下,并让我知道您可以如何使用它,或者什么可以使它更有帮助。

更新

发布此文后不久,Przemysław Kłys 很友善地分享了一些使用 PowerShell AST 提取别名信息的代码。尽管我一直在寻找使用正则表达式的方法,但他的方法要优雅得多。这是该函数的修订版本。输出不变。

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯