TheIncorrigible1 TheIncorrigible1 - 5 months ago 63
Ini Question

Unable to capture just one of two quotes

So I'm working off of this blog post in an attempt to parse

ini
files. It works for the most part, but I'm running into a specific problem I don't know enough about
regex
to solve.




Code sample:



Function Get-IniContent
{
[CmdletBinding()]
[OutputType([Hashtable])]
Param(
[Parameter(Mandatory = $True,
Position = 0,
ValueFromPipelineByPropertyName = $True)]
[Alias('FullName')]
[ValidateScript({Test-Path -Path $_})]
[String] $Path
)

Process
{
$ini = @{}

Switch -Regex -File $Path
{
'^\[(?<Section>.+)\]$'
{
$section = $Matches.Section
$ini[$section] = @{}
$commentCount = 0
}

'^;(?<Comment>.*)'
{
If (-not $section)
{
$section = 'NoSection'
$ini[$section] = @{}
}
$commentCount += 1
$ini[$section]["Comment$commentCount"] = $Matches.Comment
}

'(?<Key>.+?)\s*=\s*(?<Value>.*)'
{
If (-not $section)
{
$section = 'NoSection'
$ini[$section] = @{}
}

$ini[$section][$Matches.Key] = $Matches.Value -replace
'^"(.*)"$','$1' -replace
'\s*(.*)\s*','$1'
}
}

## Return
$ini
}
}





The problem:



In this section:

$ini[$section][$Matches.Key] = $Matches.Value -replace
'^"(.*)"$','$1' -replace
'\s*(.*)\s*','$1'


I'm running into cases where my
ini
files may have quoted values that then have strings with quotes.
Key=" this value="something here""
. I want a single regex string (ideally in the switch capture) to avoid those surrounding double-quotes.

I tried using the optional character
"?
around both sides of the value, but it only managed to skip the starting quote, but not the ending quote.




Edit



Sample string:

KeyName = "value:"ac-dii-sk""


Attempted pattern:

$HashPattern = '\s*(?<Key>.+)\s*=\s*"?\s*(?<Value>.*)\s*"?\s*'


Results:

$Matches.Key = KeyName
$Matches.Value = value:"ac-dii-sk""


Desired results:

$Matches.Key = KeyName
$Matches.Value = value:"ac-dii-sk"

Answer Source

Let's give it a try with Balancing Capture Groups.

(?<Key>.+?)\s*=\s*(?<open>")?(?<Value>.*?)(?<close-open>")?$

Test it Online

Input: KeyName = "value:"ac-dii-sk""
Captured Value: value:"ac-dii-sk"

Input: KeyName = "value:"ac-dii-sk" (1 fewer end quote)
Value: value:"ac-dii-sk

Input: KeyName = value:"ac-dii-sk"" (missing beginning quote)
Value: value:"ac-dii-sk""

Input: KeyName = value:"ac-dii-sk" (no surrounding quotes)
Value: value:"ac-dii-sk"


As I mentioned in a comment, I recommend you just use an existing library to parse INI files. Here are 2 from PSGallery:

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download