Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Powershell - Extract timestamp

i am completely new to Powershell and I am trying to create a script to extract the timestamp for the string found in a log file. There are log files everyday and it should select the latest file. It then looks for a string in that file. Now, where it finds the string it should also return a timestamp where the string is located. I am only able to complete the first part and struggling with the 2nd bit. My script is in no way optimal but it is a start. Any help is appreciated.

Set-Location -Path "O:\xyz\0502251\logs"
$latest = (Get-ChildItem -Path $dir -Filter 'async_SPARKLE_ONITE_*.log' | Sort-Object CreationDate -Descending | Select-Object -last 1).fullname
$pattern = "Successfulyl finished running psp_dba_maint_4"
$search = (Get-Content $latest | Select-String -Pattern "psp_dba_maint_4" | Select-Object -last 1)
    if($search)
    {
   
    "The overnight completed at:" 
    }
    else
    {
        "Do something"
    }

This looks for the latest file and extracts the string. Now Just want to know at what time this log was generated.

enter image description here

The log is:

Connection 1
Server message: 2022-10-15 23:56:07:020
Message number: 0, Severity 10, State 1, Line 126
Procedure 'psp_dba_locklogin'
Message String: -----> login SPRK_SVC_IRISS logged in at 23:55:45 running SRI.exe:AWAITING COMMAND on rptSPARKLE from host da-pvrep02 is still active


Connection 1
Server message: 2022-10-15 23:56:07:020
Message number: 0, Severity 10, State 1, Line 126
Procedure 'psp_dba_locklogin'
Message String: -----> login SPRK_SVC_IRISS logged in at 23:55:45 running SRI.exe:AWAITING COMMAND on rptSPARKLE from host da-pvrep05 is still active


Connection 1
Server message: 2022-10-15 23:56:07:020
Message number: 0, Severity 10, State 1, Line 126
Procedure 'psp_dba_locklogin'
Message String: -----> login SPRK_SVC_IRISS logged in at 23:55:39 running SRI.exe:SELECT on rptSPARKLE from host da-pvrep02 is still active


Connection 1
Server message: 2022-10-15 23:56:07:020
Message number: 0, Severity 10, State 1, Line 126
Procedure 'psp_dba_locklogin'
Message String: -----> login SPARKLE_CAI logged in at 23:55:37 running SPARKLE ESB (pooled):AWAITING COMMAND on A_uatSPK from host DA-UVESB01 is still active


Connection 1
Server message: 2022-10-15 23:56:07:020
Message number: 0, Severity 10, State 1, Line 355
Procedure 'psp_dba_dbrefresh'
Message String: Setting PrivShield on SPRKSZCBS OUT OF maintenance mode


Connection 1
Server message: 2022-10-15 23:56:07:022
Message number: 0, Severity 10, State 1, Line 362
Procedure 'psp_dba_dbrefresh'
Message String:  


Connection 1
Server message: 2022-10-15 23:56:07:022
Message number: 0, Severity 10, State 1, Line 364
Procedure 'psp_dba_dbrefresh'
Message String:    - Refresh 2 complete


Connection 1
Server message: 2022-10-15 23:56:07:028
Message number: 0, Severity 10, State 1, Line 42
Procedure 'psp_dba_maint_4'
Message String: Successfulyl finished running psp_dba_maint_4

This has different values in files generated everyday. So it should look for the latest file and return the result as The overnight completed at: 23:56.

like image 997
Rocky Johanson Avatar asked Oct 13 '25 04:10

Rocky Johanson


2 Answers

Here is a variant using the switch statement to efficiently process the file line-by-line and test each line to match given RegEx patterns:

$found = switch -File $latest -RegEx {
    '\d\d:\d\d' { $timestamp = $matches[0] }
    'Successfulyl finished running psp_dba_maint_4' { $true; break }
}

if( $found ) {
    "The overnight completed at: $timestamp"
}
else {
    "Not found"
}
  • $found = switch ... assigns the output of the switch statement to the variable. The output will be $true if the pattern has been found.
  • \d\d:\d\d searches for the time (first occurence of a pair of two digits separated by :) within the current line. The automatic variable $matches[0] then gives the matched value, similar to the RegEx -match operator. For a detailed explanation of the RegEx pattern and the ability to experiment with it, see this Regex101.com page.
  • Although there is no $false output of the switch statement, an empty output evaluates to $false in a boolean context (in this case the if statement), so if the pattern isn't found, the else branch will be entered.
  • There is a typo in Successfulyl which I just copied from your example ;)
like image 75
zett42 Avatar answered Oct 14 '25 22:10

zett42


To complement zett42's helpful switch-based answer:

A Select-String solution, as you attempted, is possible, via the -Context parameter, which allows you to capture the lines surrounding a matching line as well:

$time = 
  Select-String -LiteralPath $latest -Pattern 'psp_dba_maint_4' -Context 3 | 
  Select-Object -Last 1 |
  ForEach-Object {
    # Extract and output the 'HH:mm' part of the timestamp from 
    # the 3rd line above the match (the first element in the pre-context array)
    $_.Context.PreContext[0] -replace '^.+ (..:..).+$', '$1'
  }

if ($time) {
  "The overnight completed at: $time" 
} else {
  'Do something'
}

Note:

  • It is much more efficient to pass the file path of the target file to Select-String, via -LiteralPath, than it is to pass the file's content, line by line, via Get-Content.

    • If you had assigned the whole file-info object (System.IO.FileInfo), as emitted by Get-ChildItem, to $latest, you could alternatively have provided it via the pipeline: $latest | Select-String ...
  • The type of the match-information objects that Select-String emits is Microsoft.PowerShell.Commands.MatchInfo.

  • The regex-based -replace operator is used to extract (part of) the time-of-day string from the context line.

    • For an explanation of the above regex (and substitution, where $1 refers to the first and only capture group, (...)), see this regex101.com page.
like image 36
mklement0 Avatar answered Oct 14 '25 22:10

mklement0