Using regex to find PowerShell functions in PowerShell scripts

Whilst having a play with someone else’s code I wanted to quickly find all the function definitions within a module, and then all the function calls within a function definition.

Having had a quick bingle around for a prewritten regex example I didn’t come up with much that fitted the bill. So in the hope that this will help the next person trying to do this here they are:

Assumptions:

  • A PowerShell function name is of the form Word-Word
  • A PowerShell function definition is of the form “Function Word-Word”
  • A Powershell function call can be preceeded by a ‘|’,'(‘, or ‘ ‘
  • The script is written using a reasonable style, so there is a ‘ ‘ post call

So to find the function definition I ended up using:

 -match 'function\s(\w+-\w+)'

The function name ends up in $Matches[1]

And for a PowerShell function call:

-match '[^\s|(]\w+-\w+'}

The function name ends up in $Matches[0]

This works accurately enough for what I needed it to do. Feel free to let me know if you can spot any improvements on it.

2 thoughts on “Using regex to find PowerShell functions in PowerShell scripts

  1. Sunny says:

    I would recommend using AST instead of Regex for finding PS Functions /Cmdlets in scripts.
    https://blogs.technet.microsoft.com/heyscriptingguy/2012/09/26/learn-how-it-pros-can-use-the-powershell-ast/

    • Yes, you can:
      [System.Management.Automation.Language.Parser]::ParseFile('C:\github\dbatools\functions\restore-dbadatabase.ps1',[ref]$null,[ref]$Null).FindAll({$args[0] -is [System.Management.Automation.Language.CommandAst]}, $true) | ForEach {$_.commandelements[0].value} | Sort-Object -Unique

      which is faster, even when doing it recursively across an entire tree:


      Get-ChildItem C:\github\dbatools -Filter '*.ps1' -recurse | ForEach {
      [System.Management.Automation.Language.Parser]::ParseFile($_.fullname,[ref]$null,[ref]$Null).FindAll({$args[0] -is [System.Management.Automation.Language.CommandAst]}, $true) | ForEach {$_.commandelements[0].value} | Sort-Object -Unique
      }

      The only issue with that is that it matches more than just the cmdlets I was looking for. Running it recursively down the dbatools tree I’m also catching things like InModuleScope, System.Data.SqlClient.SqlException, git, TryNativeCommandOptionCompletion, ProgressBarHelper and lots of others that I didn’t want. So I’d have probably still have needed to pipe the output through a match to drop those. That’s not an issue, it’s working as designed, just not quite what I wanted 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *