Saturday, 21 May 2016

How to Parse an INI file in Powershell




Hello,

I think that all of us reading this article already know what an Ini file is. Though there may be many uses to those kinds of files, they are kind of hard to deal with when we want to access a value. I started to write this script to see if we can parse an ini file and solve, even if by little, the problem.

The problem with .ini files compared with xml file is that there are no tags to access elements.

Here’s an example of INI file content:

; last modified 1 April 2001 by John Doe
[owner]
name=John Doe
organization=Acme Widgets Inc.

[database]
; use IP address in case network name resolution is not working
server=192.0.2.62    
port=143
file="payroll.dat"

Which lines are considered as commented lines?

Lines which begin with “;” are considered as commented lines
$COMMENT_CHARACTERS = ";"

Which lines are considered as a Section header?

A section structure is always something like: [mySection01]
So, It may contains Capital letter, number and specials characters. These are the specials characters supported by this script: _ %<>/#+- , blank space is also supported. In my script, this is done by specifying a regex chains:
$HEADER_REGEX = "\[+[A-Z0-9._  %<>/#+-]+\]"

So what do we have in the Script?


  • First Step:

Useful lines are selected and set in a PScustomObject

$CONTENT_USEFUL = $ContentFile | Where { ($_ -notmatch "^\s*$COMMENT_CHARACTERS") -or ($_ -notmatch "^$COMMENT_CHARACTERS") }
$ALL_SECTION_HASHTABLE = $CONTENT_USEFUL | Where { $_ -match $HEADER_REGEX  } | % { [PSCustomObject]@{ Section= $_ ; Index = [Array]::IndexOf($CONTENT_USEFUL,$_) }}

  • Second Step

Each lines that doesn’t match the header section’s regex are stored in $SECTION_STRING and then processed

We take the index of the next section and subtract it with the current section to get the content between those two sections. However, there are cases when there is nothing between two sections (I already took that into account in the script so don’t worry).

$SECTION_STRING = $CONTENT_USEFUL | Select-Object -Index  (($SECTION_INI[$i-1].Index+1)..($SECTION_INI[$i].Index-1)) | Out-String
$CONVERTED_OBJ = convertfrom-stringdata -stringdata $SECTION_STRING

The magic function here is convertfrom-stringdata -stringdata
It really made my day. 

Here is a little example of the capabilities of this function:

$myString"
server=192.0.2.62     
port=143
file='payroll.dat'
"
ConvertFrom-StringData -StringData $myString 


Here is the output




As we can see, this function converts a string that contains one or more key and value pairs into a hashtable.

  • Last step

We put all of those elements into a big Array. :) 
The result looks like this:

Section:                                              Content:
----------                                               -------------
[owner]                                               {name,organization}
[database]                                          {server,port,file}



Here is the complete script:





Share:

2 comments:

  1. Hey,

    I need a slightly different result so here's my code. I used a few differnet pages including yours to help me with this. Thanks.


    Function Parse-IniFile ($file)
    {

    <#
    Gratitude to these people / pages
    Gottfried Bregenzer1 -- https://community.idera.com/database-tools/powershell/ask_the_experts/f/learn_powershell_from_don_jones-24/22806/convert-a-ini-file-to-xlm-array-filter-specific-values-in-the-xml-array-and-write-the-output-to-xml-and-back-to-ini-file
    dev4sys -- https://www.dev4sys.com/2016/05/how-to-parse-ini-file-in-powershell.html
    #>

    $IniSection = ""
    $IniFileTable = @()

    switch -regex -file $file
    {
    "^\[(.+)\]$"
    {
    $IniSection = $matches[1].Trim()
    #write-host "Section: $section"
    }
    '^\s*([^#].+?)\s*=\s*(.*)'
    {
    $name,$value = $matches[1..2]
    $IniParsedRecord = New-Object PSObject
    $IniParsedRecord | Add-Member -type NoteProperty -name Section -value $IniSection
    $IniParsedRecord | Add-Member -type NoteProperty -name ItemName -value $name
    $IniParsedRecord | Add-Member -type NoteProperty -name ItemValue -value $value
    $IniFileTable += $IniParsedRecord
    }
    }
    Return $IniFileTable
    }

    ReplyDelete

Popular Posts

Join us on Facebook

STATS

Contact Form

Name

Email *

Message *