Tom Kelly
Tom Kelly

Reputation: 509

How can i select "catch" code blocks using regex in powershell?

I'm trying to analyse lots of powershell scripts in a number of directories and i want to pull any Catch code blocks into a list/ variable.

I'm trying to write a regex to select any block in the following formats

    Catch 
        {
        write-Host "Function:",$MyInvocation.MyCommand,"Failed with exception:" "Error"
        write-Host "Exception: $_" "Error"
        throw "Exception: $_"
        }

    Catch{
        write-Host "Function:",$MyInvocation.MyCommand,"Failed with exception:" "Error"
        write-Host "Exception: $_" "Error"
        throw "Exception: $_" }
Catch {write-Host "Function:",$MyInvocation.MyCommand,"Failed with exception:" "Error"
        write-Host "Exception: $_" "Error"
        throw "Exception: $_"}

Essentially anywhere there is a catch followed by {}, ignoring any line breaks between the word "Catch" and the braces and after the braces, ignoring case.

I want the entire contents between the {} returned too so i can do some additional checks on it.

The best i have managed to come up with is:


\b(\w*Catch\w*)\b.*\w*{\w.*}

Which will match if its all on one line.

I'll be doing this in powershell so .net or powershell type regex would be appreciated.

Thanks.

Upvotes: 2

Views: 113

Answers (2)

Mathias R. Jessen
Mathias R. Jessen

Reputation: 174515

Don't use regex to parse PowerShell code in PowerShell

Use the PowerShell parser instead!

foreach($file in Get-ChildItem *.ps1){
    $ScriptAST = [System.Management.Automation.Language.Parser]::ParseFile($file.FullName, [ref]$null, [ref]$null)

    $AllCatchBlocks = $ScriptAST.FindAll({param($Ast) $Ast -is [System.Management.Automation.Language.CatchClauseAst]}, $true)

    foreach($catch in $AllCatchBlocks){
        # The catch body that you're trying to capture
        $catch.Body.Extent.Text

        # The "Extent" property also holds metadata like the line number and caret index
        $catch.Body.Extent.StartLineNumber
    }
}

Upvotes: 5

Emma
Emma

Reputation: 27723

My guess is that you wish to capture catch with this expression or something similar to:

\s*\bCatch\b\s*({[\s\S]*?})

that collects new lines.

Demo

and if the word boundary is not required:

\s*Catch\s*({[\s\S]*?})

Upvotes: 2

Related Questions