Powershell regular expressions: get 'not matched' portion of string? - regex

I'm not very up on powershell and have a problem.
I have a powershell script that calls a batch file that mounts a backup image (shadowprotect), runs chkdsk against mounted image, dismounts image and returns.
All the output from the batch file processing is returned to my powershell script.
I'm trying to parse this to remove all the 'progress' lines that get generated by the chkdsk command, chkdsk doesn't seem to have any way to suppress this output (on large disk images I can end up with hundreds of progress lines).
I can create regular expression to catch all the 'Progress' lines and put them out to my log file, but I can't figure out the syntax that says to give me everything that does NOT match my regular expression.
Very short example of returned value I'm trying to parse:
Try to mount d:\backups\colt\F_VOL-b001-i453-cd.spi
Mounting image chain "D:\Backups\colt\F_VOL-b001.spf|D:\Backups\colt\F_VOL-b001-i014-cd-cw.spi|D:\Backups\colt\F_VOL-b001-i018-cd.spi|D:\Backups\colt\F_VOL-b001-i022-cd.spi|D:\Backups\colt\F_VOL-b001-i026-cd.spi|D:\Backups\colt\F_VOL-b001-i030-cd.spi|D:\Backups\colt\F_VOL-b001-i445-cd.spi|D:\Backups\colt\F_VOL-b001-i449-cd.spi|D:\Backups\colt\F_VOL-b001-i453-cd.spi"
The type of the file system is NTFS.
Volume label is Local Disk - single.
WARNING! F parameter not specified.
Running CHKDSK in read-only mode.
Stage 1: Examining basic file system structure ...
Progress: 0 of 4320 done; Stage: 0%; Total: 0%; ETA: 0:00:14
Progress: 0 of 4320 done; Stage: 0%; Total: 0%; ETA: 0:00:21 .
Progress: 6 of 4320 done; Stage: 0%; Total: 0%; ETA: 0:01:10 ..
Progress: 257 of 4320 done; Stage: 5%; Total: 2%; ETA: 0:01:47 ...
Progress: 769 of 4320 done; Stage: 17%; Total: 6%; ETA: 0:01:20
Progress: 2817 of 4320 done; Stage: 65%; Total: 19%; ETA: 0:00:23 .
Progress: 4320 of 4320 done; Stage: 100%; Total: 29%; ETA: 0:00:14 ..
4320 file records processed.
File verification completed.
Progress: 0 of 0 done; Stage: 99%; Total: 46%; ETA: 0:00:13 ...
0 large file records processed.
Progress: 0 of 0 done; Stage: 99%; Total: 46%; ETA: 0:00:13
0 bad file records processed.
Stage 2: Examining file name linkage ...
Progress: 4322 of 4360 done; Stage: 99%; Total: 92%; ETA: 0:00:01 .
Progress: 4340 of 4360 done; Stage: 99%; Total: 93%; ETA: 0:00:01 ..
Progress: 4344 of 4360 done; Stage: 99%; Total: 97%; ETA: 0:00:01 ...
Progress: 4360 of 4360 done; Stage: 100%; Total: 97%; ETA: 0:00:01
4360 index entries processed.
Index verification completed.
Progress: 0 of 0 done; Stage: 99%; Total: 97%; ETA: 0:00:01 .
0 unindexed files scanned.
Progress: 0 of 0 done; Stage: 99%; Total: 97%; ETA: 0:00:01 ..
0 unindexed files recovered.
Stage 3: Examining security descriptors ...
Security descriptor verification completed.
Progress: 0 of 0 done; Stage: 100%; Total: 99%; ETA: 0:00:00 ...
20 data files processed.
Windows has scanned the file system and found no problems.
No further action is required.
145500673 KB total disk space.
15814844 KB in 748 files.
180 KB in 22 indexes.
0 KB in bad sectors.
74721 KB in use by the system.
65536 KB occupied by the log file.
129610928 KB available on disk.
4096 bytes in each allocation unit.
36375168 total allocation units on disk.
32402732 allocation units available on disk.
OK - 0
Return value is 0
My script fragment looks like this:
# call batch file...
$Out = c:\batch\Mount_and_Chkdsk_image_file.cmd $NewFilePath
# append result of batch file to the log file, remove progress lines first...
$Out -replace ("^Progress:.*$", "")
Out-File -FilePath c:\batch\log\NewFileCheck.log -Append -InputObject $Out
In above attempt, since I can match the progress lines I thought I'd just replace them with nothing but no substitution happened.
(for testing I substituted the batch file call with just a file read of the raw unfiltered log file:
$FilePath = "c:\batch\test2.txt"
$Out = [System.Io.File]::ReadAllText($filePath)
)
Anyway, since replacement didn't work, I used google and tried understanding the select-string as an option since it takes regular expressions:
$Regex = 'Pattern:.*'
$Out | select-string -pattern $Regex -notmatch
This just puts out all the lines, nothing filtered out, I had hoped 'notmatch' would mean everything that didn't match. Didn't seem to matter how I varied regex I couldn't get that to do what I needed.
Tried many many more variations on the theme like:
#$Regex = '^((Progress:).*$)'
$Regex = '([?<!Progress:].*)'
$Out | Select-String -Pattern $Regex -AllMatches | %{$_.Matches } | %{$_.value}
But I'm obviously missing something. I would have thought there would be an easy function that if you could select a certain string you could also choose to not have that selection in the output.
Can anyone please help, how do I capture all the lines that aren't a match?
Regards,
Bryce S.

Sure, this can be done. By default when you load a text file with Get-Content it will load each line as a string, and the entire file will be an array of strings. You can run that through a Where statement and use the -notmatch operator to filter out things. Usage would be as such:
$ParsedData = Get-Content "c:\batch\test2.txt" | Where{$_ -notmatch "Progress:.*$"}
That would assist $ParsedData all of the lines in the file that did not match the regex "Progress:.*$".
Edit: Ok, what you're getting from your script is most likely a multi-line string. The easiest way that I know of is to simply break your string up on the new lines to make an array of strings. Something like this:
$Out.Split("`n") | Where{$_ -notmatch "Progress:.*$"}

$Out = $Out -replace ("^Progress:.*$", "")
Out-File -FilePath c:\batch\log\NewFileCheck.log -Append -InputObject $Out
The only problem you had was that -replace doesn't modify the left side value, it just returns the result, leaving $Out unchanged, so you have to make sure you assign the result back to $Out.

Related

Split Strings in a Value column with Powercli

This is what I wrote to get output with powercli;
Get-VM -name SERVERX | Get-Annotation -CustomAttribute "Last EMC vProxy Backup"|select #{N='VM';E={$_.AnnotatedEntity}},Value
This is the output
VM Value
-- -----
SERVERX Backup Server=networker01, Policy=vmbackup, Workflow=Linux_Test_Production, Action=Linux_Test_Production, JobId=1039978, StartTime=2018-10-31T00:00:27Z, EndTime=2018-10-31T00:12:45Z
SERVERX1 Backup Server=networker01, Policy=vmbackup, Workflow=Linux_Test_Production, Action=Linux_Test_Production, JobId=1226232, StartTime=2018-12-06T00:00:29Z, EndTime=2018-12-06T00:0...
SERVERX2 Backup Server=networker01, Policy=vmbackup, Workflow=Linux_Test_Production, Action=Linux_Test_Production, JobId=1226239, StartTime=2018-12-05T23:58:27Z, EndTime=2018-12-06T00:0...
But I would like retrieve only "starttime" and "endtime" values
Desired output is;
VM Value
-- -----
SERVERX StartTime=2018-10-31T00:00:27Z, EndTime=2018-10-31T00:12:45Z
SERVERX1 StartTime=2018-12-06T00:00:29Z, EndTime=2018-1206T00:11:14Z
SERVERX2 StartTime=2018-12-05T23:58:27Z, EndTime=2018-12-06T00:11:20Z
How can I get this output?
This would be better suited in Powershell forum as this is just data manipulation.
Providing your output is always the same number of commas then
$myannotation = Get-VM -name SERVERX | Get-Annotation -CustomAttribute "Last EMC
vProxy Backup"|select #{N='VM';E={$_.AnnotatedEntity}},Value
$table1 = #()
foreach($a in $myannotation)
$splitter = $a.value -split ','
$splitbackupstart = $splitter[5]
$splitbackupend = $splitter[6]
$row = '' | select vmname, backupstart, backupend
$row.vmname = $a.AnnotatedEntity # or .vm would have to try
$row.backupstart = $splitbackupstart
$row.backupend= $splitbackupend
$table1 += $row
}
$table1
Untested. If you format of the string is going to change over time then a regex to search for starttime will be better.

How to do multiple regexp tests in TCL?

Can someone tell me what I'm doing wrong in my regexp statement? It doesn't match the "Operability: Degraded" line. I am trying to match anything that is not in operable state. I am new to TCL. Thanks!
Contents of $expect_out(buffer) it does the regexp on:
ID 20:
Location: G1
Presence: Equipped
Overall Status: Operable
Operability: Degraded
Visibility: Yes
Product Name: 16GB DDR3-1600-MHz RDIMM/PC3-12800/dual rank/1.35V
PID:
VID: V01
Vendor: 0x2C00
Vendor Description: Micron Technology, Inc.
Vendor Part Number:
Vendor Serial (SN):
HW Revision: 0
Form Factor: DIMM
Type: DDR3
Capacity (MB): 16384
Clock: 1600
Latency: 0.600000
Width: 64
Code:
proc check_errors { buffer cmd } {
set count [ regexp -all -- { Activate-Status.*?!Ready|Overall.*Status.*?!Operable|Operability.*?!Operable|Controller.*Status.*?!Optimal|Errors.*?!0|Dr
opped.*?!0|Discarded.*?!0|Bad.*?!0|Suspect.*?!No|Thresholded.*?!0|Visibility.*?!Yes|Thermal.*Status.*?!OK|HA.*?!READY } $buffer ]
if { [ set count ] != 0 } {
puts "\tFAIL $cmd (Error Count: $count)"
} else {
puts "\tPASS $cmd"
}
}
Output: (blade 6/5 has a known issue, it should fail the memory check)
Blade 6/5 checks...
PASS show stats
PASS show version
PASS show adapter detail
PASS show cpu detail
PASS show memory detail
PASS show inventory detail
!term doesn't mean "anything but term" in regex. For that type of logic, you'll need a negative lookahead approach:
Activate-Status(?!.*Ready)|Overall.*Status(?!.*Operable)|Operability(?!.*Operable)|Controller.*Status(?!.*Optimal)|Errors(?!.*0)|Dropped(?!.*0)|Discarded(?!.*0)|Bad(?!.*0)|Suspect(?!.*No)|Thresholded(?!.*0)|Visibility.(?!.*yes)|Thermal.*Status(?!.*OK)|HA.*(?!.*READY)
check it out here
note: I'd use case insensitivity to filter out both "No" and "no", and also, you must make sure your input is not treated as a single line, but multiple lines, so the .* wildcards don't race past the \n newlines and mess everything up.
#sweaver2112 has the right answer. I'd like to add maintainability into the mix:
use the -expanded flag for additional non-meaningful whitespace
use the -line so . does not match a newline (so "Ready" is on the same line as "Activate-Status")
-nocase for case-insensitive matching (if that's important)
set count [ regexp -all -expanded -line -- {
Activate-Status (?!.*?Ready) |
Overall.*Status (?!.*?Operable) |
Operability (?!.*?Operable) |
Controller.*Status (?!.*?Optimal) |
Errors (?!.*?0) |
Dropped (?!.*?0) |
Discarded (?!.*?0) |
Bad (?!.*?0) |
Suspect (?!.*?No) |
Thresholded (?!.*?0) |
Visibility (?!.*?Yes) |
Thermal.*Status (?!.*?OK) |
HA (?!.*?READY)
} $buffer ]

Remove new line after pattern and newline between 2 pattern

I have to parse and filter in linux command line only some log files.
after applying some awk and sed commands
awk -v RS='+++ ' '!/Diameter|REPT OM BLOCKED|REPT OM STARTING/ { print f $0 } {f=RT}' ./snmplog* | grep -v '+++' | grep -v '++-' | sed -e 's/^\s*//g' | sed -e '/^$/d'
I got an output like this which look like an xml file:
<Alarm>
<AlarmIndex>8865</AlarmIndex>
<ObjectName>0-0-1#RcvTCAPabortRatio^0-0-3</ObjectName>
<SpecificProblem>KPI OUTSIDE OF CRITICAL THRESHOLD</SpecificProblem>
<ProbableCause>ThresholdCrossed</ProbableCause>
<NotificationIdentifier>8865</NotificationIdentifier>
<Severity>Cleared</Severity>
<AlarmType>QualityOfServiceAlarm</AlarmType>
<AdditionalText></AdditionalText>
<OMText>REPT MEAS KPI
(RcvTCAPabortRatio^0-0-3 = 20) OUTSIDE OF CRITICAL ALARM THRESHOLD (10)</O
MText>
<AlarmCode>922044</AlarmCode>
<AlarmSource>PLATFORM</AlarmSource>
<AlarmTime>Wed Mar 11 00:15:10 2015</AlarmTime>
<RepeatCount>0</RepeatCount>
<OMDBKey>/MS044</OMDBKey>
<AutoClear>1</AutoClear>
</Alarm>
<Alarm>
<AlarmIndex>8928</AlarmIndex>
<ObjectName>0-0-1#RcvTCAPabortRatio^0-0-11</ObjectName>
<SpecificProblem>KPI OUTSIDE OF CRITICAL THRESHOLD</SpecificProblem>
<ProbableCause>ThresholdCrossed</ProbableCause>
<NotificationIdentifier>8928</NotificationIdentifier>
<Severity>Cleared</Severity>
<AlarmType>QualityOfServiceAlarm</AlarmType>
<AdditionalText></AdditionalText>
<OMText>REPT MEAS KPI
(RcvTCAPabortRatio^0-0-11 = 19) OUTSIDE OF CRITICAL ALARM THRESHOLD (10)</
OMText>
<AlarmCode>922044</AlarmCode>
<AlarmSource>PLATFORM</AlarmSource>
<AlarmTime>Wed Mar 11 00:15:10 2015</AlarmTime>
<RepeatCount>0</RepeatCount>
<OMDBKey>/MS044</OMDBKey>
<AutoClear>1</AutoClear>
</Alarm>
<Alarm>
<AlarmIndex>8771</AlarmIndex>
<ObjectName>0-0-1#SuccStandaloneISDRatio</ObjectName>
<SpecificProblem>ZERO DENOMINATOR</SpecificProblem>
<ProbableCause>CorruptData</ProbableCause>
<NotificationIdentifier>8771</NotificationIdentifier>
<Severity>Cleared</Severity>
<AlarmType>ProcessingErrorAlarm</AlarmType>
<AdditionalText></AdditionalText>
<OMText>REPT MEAS KPI
CALCULATION OF (SuccStandaloneISDRatio) FAILED FOR ZERO DENOMINATOR</OMText>
<AlarmCode>922041</AlarmCode>
<AlarmSource>PLATFORM</AlarmSource>
<AlarmTime>Wed Mar 11 01:00:10 2015</AlarmTime>
<RepeatCount>0</RepeatCount>
<OMDBKey>/MS041</OMDBKey>
<AutoClear>1</AutoClear>
</Alarm>
I would like to have after threatment something like this:
<Alarm><AlarmIndex>8771</AlarmIndex>...<OMText>REPT MEAS KPI
CALCULATION OF (SuccStandaloneISDRatio) FAILED FOR ZERO DENOMINATOR</OMText><AlarmCode>922041</AlarmCode>...</Alarm>
I have to remove all new line after > and keep new line between tags.
As you can see in my log I have an issue in the tag </OMText> in which I can have a new line also and it should be removed.
I already try with many sed regex found here, but without success
How can I do this?
[Edit]
As requested, please find below the original log file:
+++ FE01 2015-03-11 00:25:35 SNMP /SNM001 #310852 0-0-1 >
<Alarm>
<AlarmIndex>1119</AlarmIndex>
<ObjectName>0-0-3#destMMENotAvail</ObjectName>
<SpecificProblem>CLR error,Diameter Peer:p3.mmeccd.3gppnetwork.org</SpecificProblem>
<ProbableCause>CommunicationsSubsystemFailure</ProbableCause>
<NotificationIdentifier>1119</NotificationIdentifier>
<Severity>Minor</Severity>
<AlarmType>CommunicationAlarm</AlarmType>
<AdditionalText>The destination MME is not reachable</AdditionalText>
<OMText>CLR error,Diameter Peer:p3.mmeccd.3gppne
twork.org</OMText>
<AlarmCode>50906</AlarmCode>
<AlarmSource>SDM#RTLTE</AlarmSource>
<AlarmTime>Wed Mar 11 00:25:35 2015</AlarmTime>
<RepeatCount>0</RepeatCount>
<OMDBKey></OMDBKey>
<AutoClear>1</AutoClear>
</Alarm>
END OF REPORT #310852++-
+++ FE01 2015-03-11 00:25:58 SNMP /SNM001 #310853 0-0-1 >
<Alarm>
<AlarmIndex>8914</AlarmIndex>
<ObjectName>0-0-14#2AILogger.C!81</ObjectName>
<SpecificProblem>OM BLOCKED AILogger.C</SpecificProblem>
<ProbableCause>QueueSizeExceeded</ProbableCause>
<NotificationIdentifier>8914</NotificationIdentifier>
<Severity>Minor</Severity>
<AlarmType>QualityOfServiceAlarm</AlarmType>
<AdditionalText></AdditionalText>
<OMText>REPT OM BLOCKED FOR PROCESS PDLSU1
612 MESSAGES DISCARD
OM IDENTITY :
CRERROR BEING BLOCKED; FILE : AILogger.C LINE NUMBER : 81
</OMText>
<AlarmCode>906065</AlarmCode>
<AlarmSource>PLATFORM</AlarmSource>
<AlarmTime>Wed Mar 11 00:25:58 2015</AlarmTime>
<RepeatCount>0</RepeatCount>
<OMDBKey>/CR065</OMDBKey>
<AutoClear>1</AutoClear>
</Alarm>
END OF REPORT #310853++-
First I have to discared messages which contains within tags: "Diameter", "REPT OM BLOCKED" "REPT OM STARTING" then keeping only the message between the tags ...
awk '
/<Alarm>/,/<\/Alarm>/ {
sub(/^[[:blank:]]+/, "") # trim leading blanks
sub(/[[:blank:]]+$/, "") # trim trailing blanks
if (/>$/) # if the line ends with a tag
printf "%s", $0 # print it with no newline
else
print
}
/<\/Alarm>/ {print ""} # add a newline after each Alarm block
' log.file
outputs
<Alarm><AlarmIndex>1119</AlarmIndex><ObjectName>0-0-3#destMMENotAvail</ObjectName><SpecificProblem>CLR error,Diameter Peer:p3.mmeccd.3gppnetwork.org</SpecificProblem><ProbableCause>CommunicationsSubsystemFailure</ProbableCause><NotificationIdentifier>1119</NotificationIdentifier><Severity>Minor</Severity><AlarmType>CommunicationAlarm</AlarmType><AdditionalText>The destination MME is not reachable</AdditionalText><OMText>CLR error,Diameter Peer:p3.mmeccd.3gppne
twork.org</OMText><AlarmCode>50906</AlarmCode><AlarmSource>SDM#RTLTE</AlarmSource><AlarmTime>Wed Mar 11 00:25:35 2015</AlarmTime><RepeatCount>0</RepeatCount><OMDBKey></OMDBKey><AutoClear>1</AutoClear></Alarm>
<Alarm><AlarmIndex>8914</AlarmIndex><ObjectName>0-0-14#2AILogger.C!81</ObjectName><SpecificProblem>OM BLOCKED AILogger.C</SpecificProblem><ProbableCause>QueueSizeExceeded</ProbableCause><NotificationIdentifier>8914</NotificationIdentifier><Severity>Minor</Severity><AlarmType>QualityOfServiceAlarm</AlarmType><AdditionalText></AdditionalText><OMText>REPT OM BLOCKED FOR PROCESS PDLSU1
612 MESSAGES DISCARD
OM IDENTITY :
CRERROR BEING BLOCKED; FILE : AILogger.C LINE NUMBER : 81
</OMText><AlarmCode>906065</AlarmCode><AlarmSource>PLATFORM</AlarmSource><AlarmTime>Wed Mar 11 00:25:58 2015</AlarmTime><RepeatCount>0</RepeatCount><OMDBKey>/CR065</OMDBKey><AutoClear>1</AutoClear></Alarm>
To pipe (should be modified from original file like you post later)
sed '
# don t care out of section
/<Alarm>/,\#</Alarm># !d
# in section
/<Alarm>/,\#</Alarm># {
# keep line in hold buffer
H
# if not the end, loop (cycle to next line and start of script)
\#</Alarm># !b
# clean current buffer
s/.*//
# exchange buffer (current/hold)
x
# remove first new line (extra due to first keep)
s/\n//
# remove first new line
s/\n//
# reformat first part until OMText
s#\(</AlarmIndex>\).*\(<OMText>\)#\1...\2#
# reformat between AlarmCode and /Alarm
s#\(</AlarmCode>\).*\(</Alarm>\)#\1...\2#
# print result at output
}' YourFile
Self explain, posix version

Print remaining lines in file after regular expression that includes variable

I have the following data:
====> START LOG for Background Process: HRBkg Hello on 2013/09/27 23:20:20 Log Level 3 09/27 23:20:20 I Background process is using
processing model #: 3 09/27 23:20:23 I 09/27 23:20:23 I --
Started Import for External Key
====> START LOG for Background Process: HRBkg Hello on 2013/09/30 07:31:07 Log Level 3 09/30 07:31:07 I Background process is using
processing model #: 3 09/30 07:31:09 I 09/30 07:31:09 I --
Started Import for External Key
I need to extract the remaining file contents after the LAST match of ====> START LOG.....
I have tried numerous times to use sed/awk, however, I can not seem to get awk to utilize a variable in my regular expression. The variable I was trying to include was for the date (2013/09/30) since that is what makes the line unique.
I am on an HP-UX machine and can not use grep -A.
Any advice?
There's no need to test for a specific time just to find the last entry in the file:
awk '
BEGIN { ARGV[ARGC] = ARGV[ARGC-1]; ARGC++ }
NR == FNR { if (/START LOG/) lastMatch=NR; next }
FNR == lastMatch { found=1 }
found
' file
This might work for you (GNU sed):
a=2013/09/30
sed '\|START LOG.*'"$a"'|{h;d};H;$!d;x' file
This will return your desired output.
sed -n '/START LOG/h;/START LOG/!H;$!b;x;p' file
If you have tac available, you could easily do..
tac <file> | sed '/START LOG/q' | tac
Here is one in Python:
#!/usr/bin/python
import sys, re
for fn in sys.argv[1:]:
with open(fn) as f:
m=re.search(r'.*(^====> START LOG.*)',f.read(), re.S | re.M)
if m:
print m.group(1)
Then run:
$ ./re.py /tmp/log.txt
====> START LOG for Background Process: HRBkg Hello on 2013/09/30 07:31:07 Log Level 3
09/30 07:31:07 I Background process is using processing model #: 3
09/30 07:31:09 I
09/30 07:31:09 I -- Started Import for External Key
If you want to exclude the ====> START LOGS.. bit, change the regex to:
r'.*(?:^====> START LOG.*?$\n)(.*)'
For the record, you can easily match a variable against a regular expression in Awk, or vice versa.
awk -v date='2013/09/30' '$0 ~ date {p=1} p' file
This sets p to 1 if the input line matches the date, and prints if p is non-zero.
(Recall that the general form in Awk is condition { actions } where the block of actions is optional; if omitted, the default action is to print the current input line.)
This prints the last START LOG, it set a flag for the last block and print it.
awk 'FNR==NR { if ($0~/^====> START LOG/) f=NR;next} FNR>=f' file file
You can use a variable, but if you have another file with another date, you need to know the date in advance.
var="2013/09/30"
awk '$0~v && /^====> START LOG/ {f=1}f' v="$var" file
====> START LOG for Background Process: HRBkg Hello on 2013/09/30 07:31:07 Log Level 3
09/30 07:31:07 I Background process is using processing model #: 3
09/30 07:31:09 I
09/30 07:31:09 I -- Started Import for External Key
With GNU awk (gawk) or Mikes awk (mawk) you can set the record separator (RS) so that each record will contain a whole log message. So all you need to do is print the last one in the END block:
awk 'END { printf "%s", RS $0 }' RS='====> START LOG' infile
Output:
====> START LOG for Background Process: HRBkg Hello on 2013/09/30 07:31:07 Log Level 3
09/30 07:31:07 I Background process is using processing model #: 3
09/30 07:31:09 I
09/30 07:31:09 I -- Started Import for External Key
Answer in perl:
If your logs are in assume filelog.txt.
my #line;
open (LOG, "<filelog.txt") or "die could not open filelog.tx";
while(<LOG>) {
#line = $_;
}
my $lengthline = $#line;
my #newarray;
my $j=0;
for(my $i= $lengthline ; $i >= 0 ; $i++) {
#newarray[$j] = $line[$i];
if($line[$i] =~ m/^====> START LOG.*/) {
last;
}
$j++;
}
print "#newarray \n";

Powershell: regex on Get-EventLog output and find largest number

I need to pull a particular number from the output of this command:
Get-EventLog "application" | Where-Object {$_.EventID -eq 6006}
Sample output is:
Index Time EntryType Source InstanceID Message
----- ---- --------- ------ ---------- -------
18297 May 15 18:49 Warning Wlclntfy 2147489654 The winlogon notification subscriber <Profiles> took 60 second(s) to handle the notification event (Logon).
11788 Jan 31 08:11 Warning Wlclntfy 2147489654 The winlogon notification subscriber <Profiles> took 68 second(s) to handle the notification event (Logon).
5794 Oct 16 09:41 Warning Wlclntfy 2147489654 The winlogon notification subscriber <Sens> took 225 second(s) to handle the notification event (Logoff).
5596 Oct 11 08:03 Warning Wlclntfy 2147489654 The winlogon notification subscriber <Profiles> took 69 second(s) to handle the notification event (Logon).
2719 Aug 30 07:50 Warning Wlclntfy 2147489654 The winlogon notification subscriber <Profiles> took 65 second(s) to handle the notification event (Logon).
What I actually need to do is pull the number of seconds reported by the <Profiles> events, and pull out the largest one. I've gotten as far as figuring out (?<=<Profiles> took )(\d+) will work to pull just the numbers I need, but I'm not sure how to proceed to actually extract them. I've tried piping it to Select-String -pattern, but that just returns nothing at all.
You want the $matches builtin variable. $matches[0] is the text that matched the regexp, and $matches[1] .. $matches[n] are the matched parenthetical expressions (if there were any).
Sadly I don't have any EventID=6006 on my machine so I'm doing this without testing, but this should select the last item from the sorted list of seconds:
Get-EventLog "application" |
Where-Object {$_.EventID -eq 6006} |
Where-Object { $_.Message -match "<Profiles> took (\d*) second" } |
foreach { [int]$matches[1] } |
sort |
select -last 1
You can get the value(s) without regex. Take a look at the ReplacementStrings property of the event. It contains an array that holds the replacement strings stored in the event entry.
PS> $event.ReplacementStrings
Profiles
71
Logon
Based on that you could use array indexing to get the values you're after.
Get-EventLog application |
Where-Object {$_.EventID -eq 6006 -and $_.ReplacementStrings -eq 'Profiles'} |
Foreach-Object { $_.ReplacementStrings[1] }