02 / INTERFACES AND CONFIGURATION · LESSON 06

Parse a saved interface configuration

Turn a small, declared text format into typed interface objects and reject unsupported input.

15 min · learn at your pace

Parse a declared dialect

LabPort is a fictional one-line teaching format, not Cisco, Junos, or a portable configuration command language. Each non-comment line has the exact form PORT name MODE access|trunk VLAN number|- DESC description. Keywords are uppercase; modes are lowercase. The supplied descriptions can contain spaces and punctuation.

Use named regex captures for Port, Mode, VLAN, and Description. Anchor the whole line with \A and \z, and inspect captures only after a successful scalar match. $Matches can retain a previous successful match, so reading it after a failed match can silently duplicate the previous interface.

'PORT ge-1 MODE access VLAN 10 DESC Staff desks' -match 'DESC (?<text>.+)'
$Matches.text

Make invalid input visible

Ignore blank lines and lines whose first non-space character is #. Reject other unsupported lines with a terminating error. Access ports require numeric VLAN 1–4094; a trunk line uses - and produces a null AccessVlan. This is the LabPort contract, not a complete model of trunk/native/voice VLAN behaviour.

Store each capture before using another regex, because a later match can replace $Matches. Return objects without display formatting. A production importer would also need a documented policy for duplicate interfaces and partial results; this lesson's valid input contains unique interfaces.

Go deeper

Read the official reference.

Try an example.ps1
Get-Content '/home/user/ports.lab'
YOUR TURN

Put it into practice.

Define ConvertFrom-PortConfig -Lines (a string array). Parse the exact LabPort format shown above, ignoring blank/comment lines. Return Port, Mode, integer AccessVlan (null for trunk), and complete Description. Throw on malformed lines, access VLANs outside 1–4094, or a trunk VLAN other than -. Support an empty input array.

See an explained solution
One way to solve it.ps1
function ConvertFrom-PortConfig {
    param([Parameter(Mandatory)][AllowEmptyCollection()][AllowEmptyString()][string[]]$Lines)
    foreach ($line in $Lines) {
        if ([string]::IsNullOrWhiteSpace($line) -or $line.TrimStart().StartsWith('#')) { continue }
        if ($line -cnotmatch '\APORT (?<port>[A-Za-z0-9/-]+) MODE (?<mode>access|trunk) VLAN (?<vlan>-|[0-9]+) DESC (?<description>.+)\z') { throw "Unsupported line: $line" }
        $port = $Matches.port; $mode = $Matches.mode; $description = $Matches.description; $vlanText = $Matches.vlan
        $vlan = $null
        if ($mode -eq 'access') {
            if ($vlanText -notmatch '\A[0-9]+\z' -or [int]$vlanText -lt 1 -or [int]$vlanText -gt 4094) { throw 'Access VLAN must be 1 to 4094.' }
            $vlan = [int]$vlanText
        } elseif ($vlanText -ne '-') { throw 'Trunk lines use VLAN - in LabPort.' }
        [pscustomobject]@{ Port=$port; Mode=$mode; AccessVlan=$vlan; Description=$description }
    }
}

Whole-line matching establishes the grammar, copied captures avoid stale-match surprises, and mode-specific validation preserves the distinction between access VLANs and the trunk placeholder.