Files
ChocolateyPackages/core/Get-IniContent.ps1
Iristyle 45bbd1f522 Minor updates to Ini scripts
- Allow files ending in .conf in addition to .ini
- Space out values for readability in final output
2012-11-04 10:59:39 -05:00

133 lines
3.8 KiB
PowerShell

#Requires -Version 2.0
function Get-IniContent
{
<#
.Synopsis
Reads the contents of an INI file into an OrderedDictionary
.Description
The dictionary can be manipulated the same way a Hashtable can, by
adding or removing keys to the various sections.
By using an OrderedDictionary, the contents of the file can be
roundtripped through the Out-IniFile cmdlet.
Nested INI sections represented like the following are supported:
[foo]
name = value
[[bar]]
name = value
;name = value
Comment lines prefixed with a ; are returned in the output with a name
of {Comment-X} where X is the comment index within the entire INI file
Comments also have an IsComment property attached to the values, so
that Out-IniFile may properly handle them.
.Notes
Inspiration from Oliver Lipkau <oliver@lipkau.net>
http://tinyurl.com/9g4zonn
.Inputs
String or FileInfo
.Outputs
Collections.Specialized.OrderedDictionary
Keys with a OrderdedDictionary Value are representative of sections
Sections may be nested to any arbitrary depth
.Parameter Path
Specifies the path to the input file. Can be a string or FileInfo
object
.Example
$configFile = Get-IniContent .\foo.ini
Description
-----------
Parses the foo.ini file contents into an OrderedDictionary for local
reading or manipulation
.Example
$configFile = .\foo.ini | Get-IniContent
$configFile.SectionName | Select *
Description
-----------
Same as the first example, but using pipeline input.
Additionally outputs all values stored in the [SectionName] section of
the INI file.
#>
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline=$True, Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[ValidateScript({ (Test-Path $_) -and `
('.ini', '.conf' -contains $_.Extension) })]
[IO.FileInfo]
$Path
)
Process
{
Write-Verbose "[INFO]: Get-IniContent processing file [$Path]"
# TODO: once Powershell 3 is common, this can be $ini = [ordered]@{}
$ini = New-Object Collections.Specialized.OrderedDictionary
function getCurrentOrEmptySection($section)
{
if (!$section)
{
if (!$ini.Keys -contains '')
{
$ini[''] = New-Object Collections.Specialized.OrderedDictionary
}
$section = $ini['']
}
return $section
}
$comments = 0
$sections = @($ini)
switch -regex -file $Path
{
#http://stackoverflow.com/questions/9155483/regular-expressions-balancing-group
'\[((?:[^\[\]]|(?<BR> \[)|(?<-BR> \]))+(?(BR)(?!)))\]' # Section
{
$name = $matches[1]
# since the regex above is balanced, depth is a simple count
$depth = ($_ | Select-String '\[' -All).Matches |
Measure-Object |
Select -ExpandProperty Count
# root section
Write-Verbose "Parsing section $_ at depth $depth"
# handles any level of nested section
$section = New-Object Collections.Specialized.OrderedDictionary
$sections[$depth - 1][$name] = $section
if ($sections.Length -le $depth)
{
$sections += $section
}
else
{
$sections[$depth] = $section
}
}
'^(;.*)$' # Comment
{
$section = getCurrentOrEmptySection $section
$name = '{Comment-' + ($comments++) + '}'
$section[$name] = $matches[1] |
Add-Member -MemberType NoteProperty -Name IsComment -Value $true -PassThru
}
'(.+?)\s*=\s*(.*)' # Key
{
$name, $value = $matches[1..2]
(getCurrentOrEmptySection $section)[$name] = $value
}
}
Write-Verbose "[SUCCESS]: Get-IniContent processed file [$path]"
return $ini
}
}