RE: Regex parsing question
Hi Rob, Thanks ! That was helpful. Do we have a lex and Yacc equivalent in Perl ? I am writing an automation tool based on Client and server for Cisco devices. I am doing the testcase parsing in Lex and Yacc (flex and bison) to create the parser tree and then I user the server written in Perl to do all the regex jobs. ( More details are irrelevant in this context). In my test case file I wanted to specify a regular expression equivalent (a one liner) that can be generic enough for any kind of pattern matching. For eg. If my buffer contains something like this Vlan1 10.20.0.53 YES NVRAM upup Vlan2 10.21.0.1 YES NVRAM upup Vlan5 10.20.0.17 YES NVRAM upup Vlan6 10.3.4.1YES manual administratively down down Vlan7 192.168.190.5 YES NVRAM updown Vlan8 10.21.4.129 YES NVRAM updown * and I want to list out all the A Vlan which is up/up then I write an regular exp as (Not writing the actual syntax of my testcase file) Vlan(\s|\d|\.|\w|)*up(\s|\d|\.|\w|)*up and I get the result as Vlan1 10.20.0.53 YES NVRAM upup Vlan2 10.21.0.1 YES NVRAM upup Vlan5 10.20.0.17 YES NVRAM upup This was a simpler one.. But there are certain set of patterns which starts somwhere in one line, may have intermediate pattern in the middle lines and will end in another line. I just wanted a simple way of writing a oneliner regex for any kind of pattern matching such that I dont have to write any if-else code in perl. I needed a generic one liner GENERIC-REGEX such that if($buffer =~ /GENERIC-REGEX/) { print "My job is done"; } Is it possible.. or will I have to dig deeper in regex fundamentals. Thanks for ur help. Regards Rajeev -Original Message- From: Rob Dixon [mailto:[EMAIL PROTECTED] Sent: Friday, July 11, 2003 10:46 PM To: [EMAIL PROTECTED] Subject: Re: Regex parsing question Rob Dixon wrote: > Perl wrote: > > I am attempting to parse a log file that looks something like: > > > > 759033281 TE18 constructor - add to MDBTable > > EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD > > 759033281 TE18 AddRef=2 > > EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD > > 759033281 TE18 S-REXCH-MSG-07 > > 759033281 TE18 S-REXCH-MSG-06 > > 759033281 TE18 C-REXCH-MSG-07 > > 759033281 TE18 C-REXCH-MSG-06 > > 759033281 TE18 Vups_MailboxLogon done 0x0 > > 759033281 TE18 C-REXCH-MSG-06 > > 759033281 TE18 No timestamp for thread > > 759033281 TE18 IMAPISession::OpenMsgStore M > > 109 Q 0 > > > > > > The only lines I am interested in are ones that have "PHARWOOD" > > followed by a line that has "OpenMsgStore" in it. > > > > If I could explain this in English, I would want to say: > > > > "Search for an instance of "PHARWOOD" and once found print that > > line. Then search for the very next instance of "OpenMsgStore" > > that follows PHARWOOD (whether it be the next line or several > > lines down) and print that." > > > > > > > > The code I have so far works but I don't understand how to change > > my Regex filter to change from PHARWOOD to OpenMsgStore and back > > again. Or is there a simpler method? > > > > Any help welcome, > > > > --Paul > > > > > > --- > > > > $umlogs = "z\:"; > > opendir (DIR, "$umlogs") || die "Unable to open $umlogs > > because:\n$!\n"; @dirs = readdir(DIR); > > foreach $dir (@dirs) { > > if ($dir =~/^V_DEBUG/i) { > > > > > > open (LOGFILE, "$umlogs\\$dir") || die "unable to open $dir > > because:\n$!\n"; > > > > print "$umlogs\\$dir\n"; > > while () { > > my @fields = split / /; > > > > > > if (/PHARWOOD/) { > > > > print $_; > > > > > > } > > } > > } > > > > > > } > > This loop does what you ask > > print if /PHARWOOD/ .. /OpenMsgStore/ while ; > > but if your input looks like > > > PHARWOOD > : > PHARWOOD > : > OpenMsgStore > > then it will print the whole sequence, not just those lines > starting at the second 'PHARWOOD'. Is that what you want? > I'll get it right this time! The loop needs to be while () { print if /PHARWOOD/ ... /OpenMsgStore/; } as you can't modify a statement with both an if .. and a while .. Rob -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Regex parsing question
Rob Dixon wrote: > Perl wrote: > > I am attempting to parse a log file that looks something like: > > > > 759033281 TE18 constructor - add to MDBTable > > EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD > > 759033281 TE18 AddRef=2 > > EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD > > 759033281 TE18 S-REXCH-MSG-07 > > 759033281 TE18 S-REXCH-MSG-06 > > 759033281 TE18 C-REXCH-MSG-07 > > 759033281 TE18 C-REXCH-MSG-06 > > 759033281 TE18 Vups_MailboxLogon done 0x0 > > 759033281 TE18 C-REXCH-MSG-06 > > 759033281 TE18 No timestamp for thread > > 759033281 TE18 IMAPISession::OpenMsgStore M > > 109 Q 0 > > > > > > The only lines I am interested in are ones that have "PHARWOOD" > > followed by a line that has "OpenMsgStore" in it. > > > > If I could explain this in English, I would want to say: > > > > "Search for an instance of "PHARWOOD" and once found print that > > line. Then search for the very next instance of "OpenMsgStore" > > that follows PHARWOOD (whether it be the next line or several > > lines down) and print that." > > > > > > > > The code I have so far works but I don't understand how to change > > my Regex filter to change from PHARWOOD to OpenMsgStore and back > > again. Or is there a simpler method? > > > > Any help welcome, > > > > --Paul > > > > > > --- > > > > $umlogs = "z\:"; > > opendir (DIR, "$umlogs") || die "Unable to open $umlogs > > because:\n$!\n"; @dirs = readdir(DIR); > > foreach $dir (@dirs) { > > if ($dir =~/^V_DEBUG/i) { > > > > > > open (LOGFILE, "$umlogs\\$dir") || die "unable to open $dir > > because:\n$!\n"; > > > > print "$umlogs\\$dir\n"; > > while () { > > my @fields = split / /; > > > > > > if (/PHARWOOD/) { > > > > print $_; > > > > > > } > > } > > } > > > > > > } > > This loop does what you ask > > print if /PHARWOOD/ .. /OpenMsgStore/ while ; > > but if your input looks like > > > PHARWOOD > : > PHARWOOD > : > OpenMsgStore > > then it will print the whole sequence, not just those lines > starting at the second 'PHARWOOD'. Is that what you want? > I'll get it right this time! The loop needs to be while () { print if /PHARWOOD/ ... /OpenMsgStore/; } as you can't modify a statement with both an if .. and a while .. Rob -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Regex parsing question
Perl wrote: > I am attempting to parse a log file that looks something like: > > 759033281 TE18 constructor - add to MDBTable > EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD > 759033281 TE18 AddRef=2 > EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD > 759033281 TE18 S-REXCH-MSG-07 > 759033281 TE18 S-REXCH-MSG-06 > 759033281 TE18 C-REXCH-MSG-07 > 759033281 TE18 C-REXCH-MSG-06 > 759033281 TE18 Vups_MailboxLogon done 0x0 > 759033281 TE18 C-REXCH-MSG-06 > 759033281 TE18 No timestamp for thread > 759033281 TE18 IMAPISession::OpenMsgStore M > 109 Q 0 > > > The only lines I am interested in are ones that have "PHARWOOD" > followed by a line that has "OpenMsgStore" in it. > > If I could explain this in English, I would want to say: > > "Search for an instance of "PHARWOOD" and once found print that > line. Then search for the very next instance of "OpenMsgStore" that > follows PHARWOOD (whether it be the next line or several lines > down) and print that." > > > > The code I have so far works but I don't understand how to change my > Regex filter to change from PHARWOOD to OpenMsgStore and back > again. Or is there a simpler method? > > Any help welcome, > > --Paul > > > --- > > $umlogs = "z\:"; > opendir (DIR, "$umlogs") || die "Unable to open $umlogs > because:\n$!\n"; @dirs = readdir(DIR); > foreach $dir (@dirs) { > if ($dir =~/^V_DEBUG/i) { > > > open (LOGFILE, "$umlogs\\$dir") || die "unable to open $dir > because:\n$!\n"; > > print "$umlogs\\$dir\n"; > while () { > my @fields = split / /; > > > if (/PHARWOOD/) { > > print $_; > > > } > } > } > > > } This loop does what you ask print if /PHARWOOD/ .. /OpenMsgStore/ while ; but if your input looks like PHARWOOD : PHARWOOD : OpenMsgStore then it will print the whole sequence, not just those lines starting at the second 'PHARWOOD'. Is that what you want? Cheers, Rob -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Regex parsing question
Perl wrote: > I am attempting to parse a log file that looks something like: > > 759033281 TE18 constructor - add to MDBTable > EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD > 759033281 TE18 AddRef=2 > EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD > 759033281 TE18 S-REXCH-MSG-07 > 759033281 TE18 S-REXCH-MSG-06 > 759033281 TE18 C-REXCH-MSG-07 > 759033281 TE18 C-REXCH-MSG-06 > 759033281 TE18 Vups_MailboxLogon done 0x0 > 759033281 TE18 C-REXCH-MSG-06 > 759033281 TE18 No timestamp for thread > 759033281 TE18 IMAPISession::OpenMsgStore M > 109 Q 0 > > > The only lines I am interested in are ones that have "PHARWOOD" > followed by a line that has "OpenMsgStore" in it. > > If I could explain this in English, I would want to say: > > "Search for an instance of "PHARWOOD" and once found print that > line. Then search for the very next instance of "OpenMsgStore" that > follows PHARWOOD (whether it be the next line or several lines > down) and print that." > > > > The code I have so far works but I don't understand how to change my > Regex filter to change from PHARWOOD to OpenMsgStore and back > again. Or is there a simpler method? > > Any help welcome, > > --Paul > > > --- > > $umlogs = "z\:"; > opendir (DIR, "$umlogs") || die "Unable to open $umlogs > because:\n$!\n"; @dirs = readdir(DIR); > foreach $dir (@dirs) { > if ($dir =~/^V_DEBUG/i) { > > > open (LOGFILE, "$umlogs\\$dir") || die "unable to open $dir > because:\n$!\n"; > > print "$umlogs\\$dir\n"; > while () { > my @fields = split / /; > > > if (/PHARWOOD/) { > > print $_; > > > } > } > } > > > } This loop does what you ask print if /PHARWOOD/ .. /OpenMsgStore/ while ; but if your input looks like PHARWOOD : PHARWOOD : OpenMsgStore -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Regex parsing question
Perl wrote: > > I am attempting to parse a log file that looks something like: > > 759033281 TE18 constructor - add to MDBTable > EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD > 759033281 TE18 AddRef=2 > EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD > 759033281 TE18 S-REXCH-MSG-07 > 759033281 TE18 S-REXCH-MSG-06 > 759033281 TE18 C-REXCH-MSG-07 > 759033281 TE18 C-REXCH-MSG-06 > 759033281 TE18 Vups_MailboxLogon done 0x0 > 759033281 TE18 C-REXCH-MSG-06 > 759033281 TE18 No timestamp for thread > 759033281 TE18 IMAPISession::OpenMsgStore M109 > Q 0 > > The only lines I am interested in are ones that have "PHARWOOD" followed > by a line that has "OpenMsgStore" in it. > > If I could explain this in English, I would want to say: > > "Search for an instance of "PHARWOOD" and once found print that line. > Then search for the very next instance of "OpenMsgStore" that follows > PHARWOOD (whether it be the next line or several lines down) and print > that." > > The code I have so far works but I don't understand how to change my > Regex filter to change from PHARWOOD to OpenMsgStore and back again. Or > is there a simpler method? Something like this should work: my $umlogs = 'z:'; local @ARGV = <$umlogs/*>; my $found = 0; while ( <> ) { if ( /PHARWOOD/ ) { print; $found = 1; } if ( $found and /OpenMsgStore/ ) { print; $found = 0; } } __END__ John -- use Perl; program fulfillment -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Regex parsing question
I am attempting to parse a log file that looks something like: 759033281 TE18 constructor - add to MDBTable EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD 759033281 TE18 AddRef=2 EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD 759033281 TE18 S-REXCH-MSG-07 759033281 TE18 S-REXCH-MSG-06 759033281 TE18 C-REXCH-MSG-07 759033281 TE18 C-REXCH-MSG-06 759033281 TE18 Vups_MailboxLogon done 0x0 759033281 TE18 C-REXCH-MSG-06 759033281 TE18 No timestamp for thread 759033281 TE18 IMAPISession::OpenMsgStore M109 Q 0 The only lines I am interested in are ones that have "PHARWOOD" followed by a line that has "OpenMsgStore" in it. If I could explain this in English, I would want to say: "Search for an instance of "PHARWOOD" and once found print that line. Then search for the very next instance of "OpenMsgStore" that follows PHARWOOD (whether it be the next line or several lines down) and print that." The code I have so far works but I don't understand how to change my Regex filter to change from PHARWOOD to OpenMsgStore and back again. Or is there a simpler method? Any help welcome, --Paul --- $umlogs = "z\:"; opendir (DIR, "$umlogs") || die "Unable to open $umlogs because:\n$!\n"; @dirs = readdir(DIR); foreach $dir (@dirs) { if ($dir =~/^V_DEBUG/i) { open (LOGFILE, "$umlogs\\$dir") || die "unable to open $dir because:\n$!\n"; print "$umlogs\\$dir\n"; while () { my @fields = split / /; if (/PHARWOOD/) { print $_; } } } }