Musings of a Data professional

Stuart Moore

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.

Previous

Removing multiple Backup devices from an SMO restore object in PowerShell

Next

Using the Chronometer PowerShell module to analyse module performance

2 Comments

  1. Sunny

    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/

    • Avatar photo

      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 *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Powered by WordPress & Theme by Anders Norén