Puzo
Puzo

Reputation: 113

PowerShell multiline match with regex

Folks.

I'm trying to get a signature from the script. But each multiline match in PowerShell, which I'm doing not catching it.

The idea to catch lines of ===== and everything between them.

$Content = @'
Function Show-Example
{
    #Some text
    Another text
    Even more text with : like that.

    ==============================
    Org: Home Garage Inc.
    Author: Mr.Smit
    Created: 12/12/2021
    Last update: 12/12/2021
    Version: 1.1.1
    ==============================

    Other text
    And More text { Some blocks of code }
    Even more not interesting text :-)

}
'@

$FilePath = "$env:USERPROFILE\Desktop"

Set-Content -Value $Content -Path "$FilePath\Example_File.ps1"

$Content = Get-Content -Path "$FilePath\Example_File.ps1"

$Signature = $Content | Select-String -Pattern '(?smi)(====.+====(\n.+){1,}){1,}'

$Signature

What I'm doing wrong?

Upvotes: 1

Views: 1692

Answers (2)

Daniel
Daniel

Reputation: 5114

$Content = @'
Function Show-Example
{
    #Some text
    Another text
    Even more text with : like that.

    ==============================
    Org: Home Garage Inc.
    Author: Mr.Smit
    Created: 12/12/2021
    Last update: 12/12/2021
    Version: 1.1.1
    ==============================

    Other text
    And More text { Some blocks of code }
    Even more not interesting text :-)

}
'@ -split '\r?\n'

$between = $false
switch -regex ($Content) {
    '[=]{3,}' {
        $between = !$between
    }
    Default {
        if ($between) {
            $_
        }
    }
}

OR if you want to use a file directly as the input to switch

$file = 'C:\temp\powershell\test_lines.ps1'
$between = $false
switch -regex -File $file {
    '[=]{3,}' {
        $between = !$between
    }
    Default {
        if ($between) {
            $_
        }
    }
}

Upvotes: 2

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626845

First of all, you need to pass the -Raw option when you Get-Content from a file to read it into a single string variable (else, it will be processed line by line, not as a single string).

Then, you need to use

(?sm)^\s*===+\s*(.*?)\r?\n\s*====

See this regex demo. The value between ===s will be in Group 1.

Details

  • (?sm) - multiline and singleline modes on
  • ^ - start of a line
  • \s* - zero or more whitespaces
  • ===+ - three or more = chars
  • \s* - zero or more whitespaces
  • (.*?) - Group 1: any zero or more chars as few as possible
  • \r?\n - CRLF or LF line break
  • \s* - zero or more whitespaces
  • ==== - four = chars.

You may get it into Group 0, too:

(?sm)(?<=^\s*===+\r?\n\s*).*?(?=\r?\n\s*====)

where the left- and right-hand parts are wrapped with lookaround syntax. See this regex demo.

Upvotes: 2

Related Questions