powershellforeachsplitselect-stringgroup-object

how to count split words select-string pattern powershell. text file log life .txt .log


I need to count rows with values ms 2xx (where xx is any number) it can be 200,201,202,258,269 etc. (It has to start with number 2) Then do it also with numbers 4 and 5.

There In my .txt file with rows like this:

2022.10.20 13:42:01.570 | INFO | Executed action "PERPIRestEPService.Controllers.PERPIController.GetVersion (PERPIRestEPService)" in 4.9487ms
2022.10.20 13:42:01.570 | INFO | Executed endpoint '"PERPIRestEPService.Controllers.PERPIController.GetVersion (PERPIRestEPService)"'
2022.10.20 13:42:01.570 | INFO | Request finished in 5.5701ms 200 application/json; charset=utf-8
2022.10.20 13:42:01.908 | DBUG | Starting HttpMessageHandler cleanup cycle with 4 items
2022.10.20 13:42:01.908 | DBUG | Ending HttpMessageHandler cleanup cycle after 0.0105ms - processed: 4 items - remaining: 0 items
2022.10.20 13:44:30.632 | DBUG | Received data from rabbit: <?xml version="1.0"?>
<TransactionJournal xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.datapac.sk/Posybe">
  <Header>
    <GeneratedDate>2022-10-20T13:44:30.5409065+02:00</GeneratedDate>
    <BusinessDate>2022-10-20</BusinessDate>
    <SourceSystem>Posybe MCFS</SourceSystem>
    <Site>C702</Site>
    <Version>1.0</Version>

I need to make this table. It should look like this:

Count Name
----- ----
  97 200
 278 202
   2 205
  18 275

I have this code:

$files = Get-ChildItem -Path "C:\Users\krivosik\Desktop\Scripts\logs\PosybeRestEPService\*.log"
#Write-Host $files
$files | 
    Select-String -Pattern 'ms 2','ms 4' | 
    Group-Object Pattern -NoElement
    #| Select-Object Count, Name 
    
    foreach ($file in $files){
$mss=$file | Select-String -Pattern 'ms 2','ms 4'
    foreach ($l in $mss){
        $s = $l -split(" ")
        $s[9]
        $s[9] | Group-Object | Select-Object Count, Name 
        #Group-Object Pattern -NoElement |
        #Select-String -Pattern 'ms 2','ms 4'
    } 
}

I tried to split the row and now I have just the numbers I want to. Now I have to count them and make that table but I dont know how. I should be using Group-object but It just does not work for me. This is the only output I can get from this code:

Count Name                     
----- ----                     
 1463 ms 2                     
    1 ms 4                     
202

Count : 1
Name  : 202

202

Count : 1
Name  : 202

202

Count : 1
Name  : 202

202

Count : 1
Name  : 202

Solution

  • Group-Object is the right solution in this scenario. You just have to group by the value that was matched for the name, this way it accounts for the total count of how many were found with that pattern:

    Select-String -Path 'C:\Users\krivosik\Desktop\Scripts\logs\PosybeRestEPService\*.log' -Pattern '(?<=\d.*?ms )(2|4|5)\d+' | 
        Group-Object -Property { $_.Matches.Value } -NoElement
    

    As for the pattern matching, use a "positive lookbehind" to ensure the capture of what would be the name property, making it less error-prone in case something else down the line matches ms 2/4/5.

    Now, Group-Object can take the output of Select-String and group them by the values matched via Matches.Value; i.e. 2xx,4xx,5xx.

    Edit: The path on where these values are found is already exposed via Select-String but you have to bring it out using a calculated property. Also, if you want to match exact values of ms 2xx the regex following the positive lookbehind has to be changed to those values:

    Select-String -Path 'C:\Users\krivosik\Desktop\Scripts\logs\PosybeRestEPService\*.log' -Pattern '(?<=\d.*?ms )(200|202)' | 
        Group-Object -Property { $_.Matches.Value } | 
            Select-Object -Property Count, Name, @{
                Name = 'Path'
                Expression = { $_.Group[0].Path }
            }
    

    If you want to add more value to match exactly, just separated them by the | delimiter inside the ().