user1505206
user1505206

Reputation: 13

Parse Structured Text File with into CSV

I'm new to PowerShell and have searched and searched, but can't find the solution to what I'm trying to do. I'd like to monitor a set of folders and if there is a change to any text file, then I'd like to insert that data into a csv file. The text files will always be structured as the following, though the values (after a colon) may vary...

Type:   1 Red/1 Blue
SecondaryType:  
Keywords:   
Area:   150
Length: 28
Width:  22
System: 55.5cm
DateTime:   5/5/2017 10:06:38 PM
UserName:   bgates
Platform:   Major Platform 2017
CustomIdentifier:   1.11.0645.1330
Version:    14.116.65557.111

After the : there is a tab and then there may or may not be a value.

I've pieced together some code and it's exporting the csv, but not parsing correctly, I'm thinking because of the tab and often missing data. Here's my code:

$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "C:\Users\username\Desktop\03_InProgress"
$watcher.Filter = "*.txt"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true  


$action = { $path = $Event.SourceEventArgs.FullPath
            $changeType = $Event.SourceEventArgs.ChangeType
            $logline = "$(Get-Date), $changeType, $path"
            (Get-Content $path) -join "`r`n" -Split "(?m)^(?=\S)" |
                Where{$_} | 
                ForEach{
                    Clear-Variable PrimaryType,SecondaryType,Keywords,Area,Length,Width,System,DateTime,Username,Platform,CustomIdentifier,Version
                    Switch -regex ($_ -split "`r`n"){
                        "PrimaryType:" {$PrimaryType = ($_ -split ':',2)[-1].trim();Continue}
                        "SecondaryType:" {$SecondaryType = ($_ -split ':',2)[-1].trim();Continue}
                        "Keywords:" {$Keywords = ($_ -split ':',2)[-1].trim();Continue}
                        "Area:" {$Area = ($_ -split ':',2)[-1].trim();Continue}
                        "Length:" {$Length = ($_ -split ':',2)[-1].trim();Continue}
                        "Width:" {$Width = ($_ -split ':',2)[-1].trim();Continue}
                        "System:" {$System = ($_ -split ':',2)[-1].trim();Continue}
                        "DateTime:" {$DateTime = ($_ -split ':',2)[-1].trim();Continue}
                        "Username:" {$Username = ($_ -split ':',2)[-1].trim();Continue}
                        "Platform:" {$Platform = ($_ -split ':',2)[-1].trim();Continue}
                        "CustomIdentifier:" {$CustomIdentifier = ($_ -split ':',2)[-1].trim();Continue}
                        "Version:" {$Version = ($_ -split ':',2)[-1].trim();Continue}
                    }
                    [PSCustomObject]@{
                        'PrimaryType' = $PrimaryType
                        'SecondaryType' = $SecondaryType
                        'Keywords' = $Keywords
                        'Area' = $Area
                        'Length' = $Length
                        'Width' = $Width
                        'System' = $System
                        'DateTime' = $DateTime
                        'Username' = $Username
                        'Platform' = $Platform
                        'CustomIdentifier' = $CustomIdentifier
                        'Version' = $Version }

                    $Files | ForEach{ [PSCustomObject]@{'PrimaryType' = $PrimaryType; 'SecondaryType' = $SecondaryType; 'Keywords' = $Keywords; 'Area' = $Area; 'Length' = $Length; 'Width' = $Width; 'System' = $System; 'DateTime' = $DateTime; 'Username' = $Username; 'Platform' = $Platform; 'CustomIdentifier' = $CustomIdentifier; 'Version' = $Version}}
                } | Export-Csv -path "C:\Users\username\Desktop\Smart Scrape\test.csv" -NoTypeInformation
            ###Add-content "C:\Users\username\Desktop\Smart Scrape\log.txt" -value $logline
          }    
Register-ObjectEvent $watcher "Created" -Action $action
Register-ObjectEvent $watcher "Changed" -Action $action
Register-ObjectEvent $watcher "Deleted" -Action $action
Register-ObjectEvent $watcher "Renamed" -Action $action
while ($true) {sleep 5}

Upvotes: 1

Views: 339

Answers (2)

Esperento57
Esperento57

Reputation: 17492

try this

get-content $Path | ConvertFrom-Csv -Delimiter ":" -Header Name, Value | export-csv "C:\Users\jrooker\Desktop\SmartPlan Scrape\test.csv"  -notype -append

Short version with alias

gc $Path | ConvertFrom-Csv -D ":" -h Name, Value | epcsv "C:\Users\jrooker\Desktop\SmartPlan Scrape\test.csv" -not -a

Upvotes: 0

TessellatingHeckler
TessellatingHeckler

Reputation: 29048

A simple parser for one of those files could be:

$Entries = [ordered]@{}

Get-Content $Path | ForEach-Object {

    $Key, $Value = $_ -split ':', 2
    $Entries[$Key.Trim()] = $Value.Trim()

}

[PSCustomObject]$Entries | Export-Csv -Append -Path "C:\Users\jrooker\Desktop\SmartPlan Scrape\test.csv" -NoTypeInformation

Which just splits each line by colon, only splitting into 2 to avoid breaking up the datetimes which have colons in them, then takes the left and the right and stores them in a hashtable (dictionary), and then converts that to a PSCustomObject for output.

It doesn't know what the field names are, and it doesn't look like it needs to.

Upvotes: 1

Related Questions