Trying to figure out this regular expression thing…. I just can’t stand the idea of not getting it!
Joakim Svendsen Get-FolderSize uses regular expression, so I did some investigating. Why reinvent the wheel eh? 😉 Turns out there’s a lot going on under the hood here. First I had to figure out how the regular expression worked so I isolated just one…
[Regex]$regex_Dirs = 'Dirs\s:\s+(?<TotalDirs>\d+)\s+(?<CopiedDirs>\d+)(?:\s+\d+){2}\s+(?<FailedDirs>\d+)\s+\d+'
Turns out you can give your result a label if a match is found. Running the regular expression with -match operator will populate the $Matches variable with found label/value, which allows you to retrieve that value later on.
if ($_ -match $regex_Dirs){ $rcLog.TotalDirs = [int]$Matches['TotalDirs'] $rcLog.CopiedDirs = [int]$Matches['CopiedDirs'] $rcLog.FailedDirs = [int]$Matches['FailedDirs'] }
Quick side note: This script works with the /Bytes option. The plus side of using /Bytes is that you can do some fun stuff like calculating the size in GB or MB
TotalBytes = $Matches['ByteCount'] TotalMBytes = ([int64] $Matches['ByteCount'] / 1MB).ToString('N') TotalGBytes = ([int64] $Matches['ByteCount'] / 1GB).ToString('N')
Nice!
There’s yet another option, using ConvertFrom-String, an excellent blog by Bartek Bielawski brought to my attention by Dexter Dhami. I’m working on that as well. That one will only work with PowerShell version 5 so there’s that. Actually, I saw this feature in ISESteroids first at the PowerShell Summit. What I did notice is when using ConvertFrom-String performance took quite a hit…
I have mixed feelings when it comes to ConvertFrom-String. At times he just doesn’t get it! I love the template idea but you need to be specific, otherwise some data might fall through the cracks…You never know for sure… Like all tools you should be skilled at several. Think of regular expression as driving a stick and ConvertFrom-String as an automatic. Here in the Netherlands you can get your driver license on an automatic, but then you’re not allowed to drive stick ever! But if you pass driving a stick you’re allowed to drive automatic. Best bet, go with stick!
Here’s the code using regular expression, with a lil’ help from my friends… 😉
#region Hash with the Robocopy Log properties $rcLogProperties = [Ordered]@{ rcLogFile = '' Source = '' Target = '' TotalDirs = '' CopiedDirs = '' FailedDirs = '' TotalFiles = '' CopiedFiles = '' FailedFiles = '' TotalBytes = '' CopiedBytes = '' FailedBytes = '' StartTime = '' EndTime = '' Speed = '' } #endregion #region Main #Get Logfiles from folder Get-ChildItem '.\temp\23-06-2015' -File | ForEach-Object { #Get Lofile Header & Footer $arrSummary = (Get-Content $_.FullName)[5..8] $arrSummary += (Get-Content $_.FullName)[-10..-1] $rcLog = New-Object -TypeName psobject -Property $rcLogProperties $rcLog.rcLogFile = $_.Name Foreach($line in $arrSummary) { switch ($line){ {$_ -like '*Source :*'} { $rcLog.Source = ($_ -replace '(\s\w+)(\s.)','').Trim() } {$_ -like '*Dest :*'} { $rcLog.Target = ($_ -replace '(\s\w+)(\s.)','').Trim() } {$_ -like '*Dirs :*'} { [regex]$regex_Dirs = 'Dirs\s:\s+(?<TotalDirs>\d+)\s+(?<CopiedDirs>\d+)(?:\s+\d+){2}\s+(?<FailedDirs>\d+)\s+\d+' if ($_ -match $regex_Dirs){ $rcLog.TotalDirs = [int]$Matches['TotalDirs'] $rcLog.CopiedDirs = [int]$Matches['CopiedDirs'] $rcLog.FailedDirs = [int]$Matches['FailedDirs'] } } {$_ -like '*Files :*'} { [regex]$regex_Files = 'Files\s:\s+(?<TotalFiles>\d+)\s+(?<CopiedFiles>\d+)(?:\s+\d+){2}\s+(?<FailedFiles>\d+)\s+\d+' if ($_ -match $regex_Files){ $rcLog.TotalFiles = [int]$Matches['TotalFiles'] $rcLog.CopiedFiles = [int]$Matches['CopiedFiles'] $rcLog.FailedFiles = [int]$Matches['FailedFiles'] } } {$_ -like '*Bytes :*'} { [regex]$regex_Bytes = 'Bytes\s:\s+(?<TotalBytes>\d+)\s+(?<CopiedBytes>\d+)(?:\s+\d+){2}\s+(?<FailedBytes>\d+)\s+\d+' if ($_ -match $regex_Bytes){ $rcLog.TotalBytes = $Matches['TotalBytes'] $rcLog.CopiedBytes = $Matches['CopiedBytes'] $rcLog.FailedBytes = $Matches['FailedBytes'] } } {$_ -like '*Ended :*'} { [regex]$regex_End = 'Ended\s:\s+(?<EndTime>.+)' if ($_ -match $regex_End){ $rcLog.EndTime = $Matches['EndTime'] } } {$_ -like '*Started :*'} { [regex]$regex_Start = 'Started\s:\s+(?<StartTime>.+)' if ($_ -match $regex_Start){ $rcLog.StartTime = $Matches['StartTime'] } } {$_ -like '*Speed :*'} { [regex]$regex_Speed = 'Speed\s:\s+(?<Speed>.+\/min)' if ($_ -match $regex_Speed){ $rcLog.Speed = $Matches['Speed'] } } } } $rclog }| Out-GridView #endregion
Hope it’s worth something to you!
Ttyl,
Urv
Pingback: RoboCopy class | pshirwin