Scott R
Scott R

Reputation: 13

Manipulating Text after Get-Content

I have a log file that I have to scan every 5 minutes for specific keywords - specifically "Order Failed" then capture the lines around that. I have that part programmed with no issues. The rest of the log entries don't matter. I'm able to use the command:

[string] $readFile = get-content c:\test\friday.log | select-String -pattern '(order.*failed)' -context 1,7

which outputs:

Message: Order submission failed.


Timestamp: 4/1/2016 4:05:09 PM

Severity: Error

Message: Modifier not authorized for parent item


Message: Order submission failed.


Timestamp: 4/1/2016 4:18:15 PM

Severity: Error

Message: Modifier not authorized for parent item


Which is exactly what I want. My problem is trying to read through the above output and store the "Timestamp" into a variable that I can manipulate. The first challenge is the "Timestamp" time is written in UTC time and we are located in the Pacific Time Zone. The second challenge is I need to compare the "Timestamp" time to the current time and store that as an integer. We only want to report errors that are within 5 minutes of the current time.

My current code only grabs the first "Timestamp" entry since I hard-coded it:

[string] $readFile = get-content c:\test\friday.log | select-String -pattern '(order.*failed)' -context 1,7
$fileArray = $readFile.Split(“`n”)
[dateTime] $TrimTime = $fileArray[3].trim("Timestamp: ")
[dateTime] $currentTime = get-date
[int32] $getMinutes = (new-timespan -start $TrimTime -end $currentTime).minutes

I don't know how to loop through the output of the Get-content - to check for all of the Timestamps - we only want to report errors that are within 5 minutes of the current time.

Upvotes: 0

Views: 106

Answers (1)

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200293

Don't cast your matches to a string right away.

$readFile = get-content c:\test\friday.log | select-String -pattern '(order.*failed)' -context 1,7

If you leave the MatchInfo objects intact for the time being you can extract the timestamps from the aftercontexts like this:

$readFile | ForEach-Object {
  $_.Context.AfterContext | Where-Object {
    $_ -match 'timestamp: (\d{1,2}/\d{1,2}/\d{4} \d{1,2}:\d{2}:\d{2} [ap]m)'
  } | ForEach-Object {
    $timestring = $matches[1]
  }
}

Use the ParseExact() method to convert the matched substring to a DateTime value:

$fmt     = 'M\/d\/yyyy h:mm:ss ttK'
$culture = [Globalization.CultureInfo]::InvariantCulture

$timestamp = [DateTime]::ParseExact("${timestring}Z", $fmt, $culture)

The Z that is appended to $timestring indicates the UTC timezone and the trailing K in the format string makes the method recognize it as such. The result is automatically converted to your local time. If you need the time in UTC: append .ToUniversalTime() to the method call.

Upvotes: 2

Related Questions