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.
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
.
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.$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.Successfulyl
which I just copied from your example ;)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
.
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.
$1
refers to the first and only capture group, (...)
), see this regex101.com page.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With