有没有一种方法可以显示PowerShell脚本中的所有函数?

3

有没有命令可以列出我在脚本中创建的所有函数?

比如我创建了 doXY 函数和 getABC 函数之类的。

然后我输入命令,它会显示:

  1. 函数 doXY
  2. 函数 getABC

这将是一个很酷的功能^^

感谢您的所有帮助。


2
类似于在 MacOS/Linux 中使用 cat ./things.ps1 | grep function 或者在 Windows 中使用 cat ./things.ps1 | select-string function 这样的命令无法满足您的需求吗?其中,您的脚本名为 things.ps1 - Adam
2
这解决了我的问题^^ 谢谢 - DragonCoder
2
你能写成答案吗,这样我就可以标记我的帖子为已回答了;) 如果不行也没关系xD - DragonCoder
4个回答

4
你可以让PowerShell解析你的脚本,然后在生成的抽象语法树(AST)中找到函数定义。
使用Get-Command可能是访问AST最简单的方式:
# Use Get-Command to parse the script
$myScript = Get-Command .\path\to\script.ps1
$scriptAST = $myScript.ScriptBlock.AST

# Search the AST for function definitions
$functionDefinitions = $scriptAST.FindAll({
  $args[0] -is [Management.Automation.Language.FunctionDefinitionAst]
}, $false)

# Report function name and line number in the script
$functionDefinitions |ForEach-Object {
    Write-Host "Function '$($_.Name)' found on line $($_.StartLineNumber)!"
}

您可以使用这个工具来分析函数的内容和参数(如果需要)。

你如何在不获取整个文件的情况下获取函数内容? - not2qubit
@not2qubit 你能具体说明一下吗?你想要实现什么目标? - Mathias R. Jessen
@ Mathias,我正在尝试像这样做。即模仿Bash内部的typset -f - not2qubit
@not2qubit,我不知道typset -f是什么,但你无法在不读取文件的情况下枚举和执行文件中的函数定义。 - Mathias R. Jessen
@MathiasR.Jessen,看到你的评论,没有读取文件就无法查看定义?在Linux中是使用define -f - Timo
1
@Timo,你可以使用“ls function:”轻松获取函数定义,但是OP特别要求了包含在文件中的函数定义。 - Mathias R. Jessen

2

如果你的脚本名叫 things.ps1,那么类似于...

cat ./things.ps1 | grep function

For MacOS/Linux or...

cat ./things.ps1 | select-string function

适用于Windows。


1
这个函数将解析包含在.ps1文件中的所有函数,并为找到的每个函数返回对象。
输出可以直接传递给Invoke-Expression,以将返回的函数加载到当前范围中。
您还可以提供一个所需名称的数组,或者使用正则表达式来限制结果。
我的用例是我需要一种从较大的脚本中加载单个函数的方法,而这些脚本不属于我自己,这样我就可以进行Pester测试。
注意:仅在PowerShell 7中进行了测试,但我怀疑它也适用于旧版本。
function Get-Function {
    <# 
    .SYNOPSIS 
        Returns one or more named functions from a .ps1 file without executing the file

    .DESCRIPTION
        This is useful where you have a blended file containing functions and executed instructions.

        If neither -Names nor -Regex are provided then all functions in the file are returned.
        Returned objects can be piped directly into Invoke-Expression which will place them into the current scope.

        Returns an array of objects with the following
            - .ToString()
            - .Name
            - .Parameters
            - .Body
            - .Extent
            - .IsFilter
            - .IsWorkFlow
            - .Parent

    .PARAMETER -File
        String; Mandatory
        Path of file to parse

    .PARAMETER -Names 
        Array of Strings; Optional
        If provided then function objects of these names will be returned
        The name must exactly match the provided value
        Case Insensitive.

    .PARAMETER -Regex
        Regular Expression; Optional
        If provided then function objects with names that match will be returned
        Case Insensitive

    .EXAMPLE
        Get all the functions names included in the file
            Get-Function -name TestA | select name

    .EXAMPLE
        Import a function into the current scope
            Get-Function -name TestA | Invoke-Expression

    #>
    param (
        [Parameter(Mandatory = $true)]
        [alias("Path", "FilePath")]
        $File
        
        , 
        [alias("Name", "FunctionNames", "Functions")]
        $Names

        ,
        [alias("NameRegex")]
        $Regex
        ) # end param

    # get the script and parse it
    $Script = Get-Command $File
    $AllFunctions = $Script.ScriptBlock.AST.FindAll({$args[0] -is [Management.Automation.Language.FunctionDefinitionAst]}, $false)

    # return all requested functions
    $AllFunctions | Where-Object {
        ( $Names -icontains $_.Name ) `
        -or ( $Regex -imatch $_.Name ) `
        -or (-not($Names) -and -not($Regex))
        } # end where-object
    } # end function Get-Function

1

这是 PowerShell 帮助文件中显示的内置功能。

关于提供程序

类似的问题以前已经被问过了。因此,这可能是一个重复的问题:

如何获取自定义 Powershell 函数列表?

答案是使用 PSDrive 功能。

# To get a list of available functions
Get-ChildItem function:\

# To remove a powershell function
# removes `someFunction`
Remove-Item function:\someFunction

或者

Function Get-MyCommands {
    Get-Content -Path $profile | Select-String -Pattern "^function.+" | ForEach-Object {
        [Regex]::Matches($_, "^function ([a-z.-]+)","IgnoreCase").Groups[1].Value
    } | Where-Object { $_ -ine "prompt" } | Sort-Object
}

或者这个

从脚本中获取函数列表

$currentFunctions = Get-ChildItem function:
# dot source your script to load it to the current runspace
. "C:\someScript.ps1"
$scriptFunctions = Get-ChildItem function: | Where-Object { $currentFunctions -notcontains $_ }

$scriptFunctions | ForEach-Object {
      & $_.ScriptBlock
}

关于这个问题...

谢谢,这很接近我想要的,但它也显示了像A:,B:,Get-Verb,Clear-Host等函数。

这是预期的结果。如果您想以其他方式获得它,那么您必须编写代码。 要获取任何脚本中函数的名称,首先必须将其加载到内存中,然后可以点源定义并获取其内部信息。如果您只想要函数名称,您可以使用正则表达式来获取它们。

或者简单地说...

Function Show-ScriptFunctions
{
    [cmdletbinding()]
    [Alias('ssf')]

    Param 
    (
        [string]$FullPathToScriptFile
    )


    (Get-Content -Path $FullPathToScriptFile) | 
    Select-String -Pattern 'function'
}

ssf -FullPathToScriptFile 'D:\Scripts\Format-NumericRange.ps1'

# Results
<#
function Format-NumericRange 
function Flush-NumberBuffer 
#>

1
谢谢,这大概是我想要的,但它也显示了像 A:、B:、Get-Verb、Clear-Host 等函数。 - DragonCoder
如果您想仅获取特定函数,其中您(多或少)知道其名称,请使用命令补全(TAB)并输入以下内容:get-content Function: - not2qubit
小心使用点操作符引入脚本,因为这将执行脚本,并处理不在函数内的任何代码行。 - Ro Yo Mi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接