Public/ConvertFrom-NSPTextLog.ps1

function ConvertFrom-NSPTextLog {
    [CmdletBinding(DefaultParameterSetName = 'Text')]
    param(
        [Parameter(Mandatory, ParameterSetName = 'Text', ValueFromPipeline)]
        [AllowEmptyString()][string[]]$InputObject,
        [Parameter(Mandatory, ParameterSetName = 'File')]
        [ValidateNotNullOrEmpty()][string]$Path,
        [Parameter(Mandatory)][ValidateNotNullOrEmpty()][System.Collections.IDictionary]$PatternSet,
        [ValidateSet('Line', 'WholeText')][string]$RecordMode = 'Line'
    )

    begin {
        $compiled = @()
        foreach ($name in $PatternSet.Keys) {
            if ([string]::IsNullOrWhiteSpace([string]$name)) { throw 'Pattern names cannot be blank.' }
            $source = [string]$PatternSet[$name]
            if ([string]::IsNullOrWhiteSpace($source)) { throw "Pattern '$name' is empty." }
            $regex = New-Object System.Text.RegularExpressions.Regex($source, ([System.Text.RegularExpressions.RegexOptions]::Compiled), ([timespan]::FromSeconds(2)))
            $compiled += [pscustomobject]@{ Name = [string]$name; Regex = $regex }
        }
        if ($compiled.Count -eq 0) { throw 'PatternSet must contain at least one pattern.' }
        $textParts = New-Object 'System.Collections.Generic.List[string]'
        $recordNumber = 0
    }

    process {
        if ($PSCmdlet.ParameterSetName -eq 'Text') {
            foreach ($part in $InputObject) {
                if ($RecordMode -eq 'WholeText') { $textParts.Add($part); continue }
                $recordNumber++
                foreach ($entry in $compiled) {
                    foreach ($match in $entry.Regex.Matches($part)) {
                        $captures = [ordered]@{}
                        foreach ($groupName in $entry.Regex.GetGroupNames()) {
                            if ($groupName -eq '0' -or $groupName -match '^\d+$') { continue }
                            $group = $match.Groups[$groupName]
                            if ($group.Success) { $captures[$groupName] = $group.Value }
                        }
                        [pscustomobject]@{ PatternName = $entry.Name; RecordNumber = $recordNumber; MatchValue = $match.Value; Captures = [pscustomobject]$captures }
                    }
                }
            }
        }
    }

    end {
        if ($PSCmdlet.ParameterSetName -eq 'File') {
            $resolved = (Resolve-Path -LiteralPath $Path -ErrorAction Stop).ProviderPath
            if ($RecordMode -eq 'WholeText') { $textParts.Add([IO.File]::ReadAllText($resolved)) }
            else {
                foreach ($line in [IO.File]::ReadLines($resolved)) {
                    $recordNumber++
                    foreach ($entry in $compiled) {
                        foreach ($match in $entry.Regex.Matches($line)) {
                            $captures = [ordered]@{}
                            foreach ($groupName in $entry.Regex.GetGroupNames()) {
                                if ($groupName -eq '0' -or $groupName -match '^\d+$') { continue }
                                $group = $match.Groups[$groupName]
                                if ($group.Success) { $captures[$groupName] = $group.Value }
                            }
                            [pscustomobject]@{ PatternName = $entry.Name; RecordNumber = $recordNumber; MatchValue = $match.Value; Captures = [pscustomobject]$captures }
                        }
                    }
                }
            }
        }
        if ($RecordMode -eq 'WholeText') {
            $allText = [string]::Join([Environment]::NewLine, $textParts)
            foreach ($entry in $compiled) {
                foreach ($match in $entry.Regex.Matches($allText)) {
                    $captures = [ordered]@{}
                    foreach ($groupName in $entry.Regex.GetGroupNames()) {
                        if ($groupName -eq '0' -or $groupName -match '^\d+$') { continue }
                        $group = $match.Groups[$groupName]
                        if ($group.Success) { $captures[$groupName] = $group.Value }
                    }
                    [pscustomobject]@{ PatternName = $entry.Name; RecordNumber = 1; MatchValue = $match.Value; Captures = [pscustomobject]$captures }
                }
            }
        }
    }
}