davesnb
asked on
powershell and select-string regex multi line
Hello Ee,
I have the below entries dumped to a text file , the issue is i need to parse through them and filter for ips etc. Currently, I am unabel to get a good regex for multiline, with the intention of 6 capture groups ( date , Type , method, clientip,username,end) . The end of the entry wil have a "###" and that will be the last capture group .
ideally,Also tried to use the non capture group format " (?:.*\r?\n?)" between the capture groups with no luck, please help .
Once I have a good regex, i can convert to object , run a parse exact on the date and build up an array.
I have the below entries dumped to a text file , the issue is i need to parse through them and filter for ips etc. Currently, I am unabel to get a good regex for multiline, with the intention of 6 capture groups ( date , Type , method, clientip,username,end) . The end of the entry wil have a "###" and that will be the last capture group .
(\d\/\d\d\/\d\d\d\d\s\d\d:\d\d:\d\d\s..)?(TYPE = .*)?(Method = .*)?(ClientIP = \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})?(Username = .*)?(###)?
ideally,Also tried to use the non capture group format " (?:.*\r?\n?)" between the capture groups with no luck, please help .
Once I have a good regex, i can convert to object , run a parse exact on the date and build up an array.
4/28/2017 12:46:46 AM
TYPE = [REQUEST]
Namespace = Company.Test.API
Class = AgencyAccountService
Method = GetCompanyDetails()
ClientIP = 111.111.111.226
CompanyDetailsRequest = <?xml version="1.0" encoding="utf-16"?>
<CompanyDetailsRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<AuditKey>00000000-0000-0000-0000-000000000000</AuditKey>
<CompanyCode>37385670</CompanyCode>
</CompanyDetailsRequest>
Username = SOMEUSER
Cert =
###
A touch more complex, but it'll get you more than one record.
$pattern = '(?<DateTime>(?:\d{1,2}/){2}\d{2,4} (?:\d{1,2}:){2}\d{1,2} [AP]M)\n' +
'TYPE = \[(?<Type>[^\]]+)\]\n' +
'(?:(?:Namespace|Class).+\n){2}' +
'Method = (?<Method>.+)\n' +
'ClientIP = (?<ClientIP>(?:\d{1,3}\.){3}\d{1,3})\n' +
'CompanyDetailsRequest = .+\n' +
'(?:\s*<.+\n)*' +
'Username = (?<UserName>\S+)\n'
$regex = New-Object regex($pattern)
if ($regexMatches = $regex.Matches($sample)) {
foreach ($match in $regexMatches) {
$result = @{}
foreach ($name in $regex.GetGroupNames()) {
$result.$name = $match.Groups[$name].Value
}
$result.Remove('0')
[PSCustomObject]$result
}
}
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
I'd use a Switch over that rather than a single regex. Has the advantage that you can convert your text input to the target type right there and then.
$Content = Get-Content -Path C:\Temp\Whatever.txt
$DTProvider = New-Object -TypeName System.Globalization.CultureInfo -ArgumentList 'en-US'
Switch -regex ($Content) {
'\A\d+/\d+/\d+\s\d+:\d+:\d+\s[A|P]M\Z' {
$ReturnObject = '' | Select-Object -Property Date, Type, Method, ClientIP, Username
$ReturnObject.Date = [DateTime]::Parse($_, $DTProvider)
}
'\ATYPE\s*=\s*\[(?<Type>.*)\]\Z' {$ReturnObject.Type = $Matches['Type']}
'\AMethod\s*=\s*(?<Method>.*)\s*\Z' {$ReturnObject.Method = $Matches['Method']}
'\AClientIP\s*=\s*(?<ClientIP>.*)\s*\Z' {$ReturnObject.ClientIP = $Matches['ClientIP']}
'\AUsername\s*=\s*(?<Username>.*)\s*\Z' {$ReturnObject.Username = $Matches['Username']}
'\A###\Z' {$ReturnObject}
}
ASKER
Thanks guys , so I have a few options there with the regex , as I have been using a convert-textobject and parseexaact for datetime prior so I will go with the more simpler one, but if there are numerous of these entries and I want to store each one into an array ..IS it the -AllMatches | % { $_.Matches } | % { $_.Value } ?
$recentlog = gci C:\Scripts\ClientReports\WIP\APIv3\web13\ -recurse
foreach ($log in $recentlog ) {
$multi += gc $log.fullname
}
$pattern1 = "(\d\/\d\d\/\d\d\d\d\s\d\d:\d\d:\d\d\s..)(?:[\n]*)(TYPE = .*)(?:[\s\S]*?)(Method = .*)(?:[\s\S]*?)(ClientIP = \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?:[\s\S]*?)(Username = .*)(?:[\s\S]*?)(###)"
$logContent1 = $multi| Select-String -pattern $pattern1 -AllMatches | % { $_.Matches } | % { $_.Value }
ASKER
Actually , nevermind , I used your Switch -regex ($Content) {
}
and that is pretty slick.. Just needed some time to walk through it as it is very busy..( and i am still catching up to everything it does ) ..;)
}
and that is pretty slick.. Just needed some time to walk through it as it is very busy..( and i am still catching up to everything it does ) ..;)
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks GUys !
pls try
Open in new window
Regards