Question

I am trying to return the sections of an INI file as an array of captures using a regular expression:

\[[^\]\r\n]+](?:\r?\n(?:[^\[\r\n].*)?)*

This works in just about every regex checker I have tried, including one using .NET, but when I try it in my program, it only selects the section headers, not the bodies.

I'm working in Powershell, but I'm explicitly creating a Regex object using New-Object, not the built-in -match operator. I'm at a bit of a loss since it works outside my environment but not inside it.

Update: Ansgar reminds me that I should have shown my code, so here it is.

$IniRegex = New-Object System.Text.RegularExpressions.Regex("\[[^\]\r\n]+](?:\r?\n(?:[^\[\r\n].*)?)*")
$TestIni = Get-Content "C:\Test.ini"
$SectionsMatches = $IniRegex.Matches($TestIni)

$SectionsMatches.Count
$SectionsMatches[0].Captures[0].ToString()
$SectionsMatches[1].Captures[0].ToString()

The Test.ini file contains some sample settings:

[Test0]
Setting0=0
Setting1=1

[Test1]
Setting2=2
Setting3=3

The output from the code is:

2
[Test0]
[Test1]
Was it helpful?

Solution

If you're on PowerShell 3 or higher, add -Raw to the end of Get-Content. By default, Get-Content returns an array of strings, with one element corresponding to one line. But you want to match against a single string:

$IniRegex = New-Object System.Text.RegularExpressions.Regex("\[[^\]\r\n]+](?:\r?\n(?:[^\[\r\n].*)?)*")
$TestIni = Get-Content "C:\Test.ini" -Raw
$SectionsMatches = $IniRegex.Matches($TestIni)

$SectionsMatches.Count
$SectionsMatches[0].Captures[0].ToString()
$SectionsMatches[1].Captures[0].ToString()

If you're on v2, you can do this instead:

$TestIni = (Get-Content "C:\Test.ini") -join ''

Also, you can shorten the line where you create the regex quite a bit, by using the [regex] type accelerator:

$IniRegex = [regex]"\[[^\]\r\n]+](?:\r?\n(?:[^\[\r\n].*)?)*"
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top