Alessandro
Alessandro

Reputation: 313

Powershell split sections by regex

In order to create a script which allows me to perform a firewall migration, i have the need to understand how to split an output into sections with Powershell.

The firewall (which is a Sonicwall, if it helps) produces an output, which is delimited by sections. For example:

--System Information--
[Data]
--Network Interfaces--
[Data]
--User Objects Table--
[Data]
...

You can see that the output is delimited by these sections, for which i have produced a regex:

$regex1='^--(\w*|\w+ \w+|\w+ \w+ \w+|\w+ \w+ \w+ \w+)--$'

I don't understand however, how can i produce an output which helps me put a specific section title above, and the data directly below. I don't want all of them, just specific outputs from specific sections.

Any help would be much appreciated,

Thanks a lot in advance

Upvotes: 0

Views: 123

Answers (2)

f6a4
f6a4

Reputation: 1782

I would prefer an approach with a data table:

$configFile = 'C:\sonciwall\sonicwall.txt'

$dt = New-Object system.Data.DataTable
[void]$dt.Columns.Add('Section',[string]::empty.GetType() )
[void]$dt.Columns.Add('Data',[string]::empty.GetType() )

foreach( $line in Get-Content $configFile ) {

    $line = $line.Trim()

    if( !$line ) {
        Continue       # skip empty lines
    }
    elseif( $line -like '--*' ) {
        $section = $line
        Continue
    }
    else {
        $data    = $line
    }

    $newRow = $dt.NewRow()
    $newRow.Section = $section
    $newRow.Data    = $data
    [void]$dt.Rows.Add( $newRow )

}

# Get specific information from a specific section using sql syntax:

$dt.Select("Section = '--System Information--' AND Data = 'foo'")

# Update specific information in all secions:

$rows = $dt.Select("Data = 'foo'")

foreach( $row in $rows ) {
    $row.Data = 'foo bar'
    [void]$dt.AcceptChanges()
}

Upvotes: 1

Manuel Batsching
Manuel Batsching

Reputation: 3606

A complex multi-line regex might be a bit to much in your case. A very simple approach would be to go through the content line by line:

$content = @"
--System Information--
[Data1]
--Network Interfaces--
[Data2]
[Data3]
--User Objects Table--
[Data4]
"@ -split [System.Environment]::NewLine

$dataDict = @{}
foreach ($line in $content)
{   
    # Each section opens a new entry in the $dataDict hash table.
    # Anything else that follows, gets added to this entry.
    if($line -match '^--(.+)--$')
    {
        $section = $Matches[1]
        $dataDict[$section] = @()
    }
    else 
    {
        $dataDict[$section] += $line
    }
}
# You can now narrow down the resulting object to the properties, 
# that you are interested in.
[pscustomobject]$dataDict | 
    Select-Object 'System Information', 'Network Interfaces' | 
    Format-List

Upvotes: 3

Related Questions