XML parsing question
Hi List , I have a xml file which looks like BSC id=AMIBRB1 ALPHA10/ALPHA AMRCSFR3MODE1,3,4,7/AMRCSFR3MODE AMRCSFR3THR12,16,21/AMRCSFR3THR AMRCSFR3HYST2,3,3/AMRCSFR3HYST AMRCSFR4MODE1,3,6,8/AMRCSFR4MODE AMRCSFR4THR12,17,25/AMRCSFR4THR PAGBUNDLE50/PAGBUNDLE USERDATAAMI_BRANLY_B_1/USERDATA /BSC BSC id=BAYHAB1 ALPHA10/ALPHA AMRCSFR3MODE1,3,4,7/AMRCSFR3MODE AMRCSFR3THR12,16,21/AMRCSFR3THR AMRCSFR3HYST2,3,3/AMRCSFR3HYST AMRCSFR4MODE1,3,6,8/AMRCSFR4MODE REESTON/REEST REPFACCHON/REPFACCH BCCHNORMAL0/BCCHNORMAL /BSC I need to create a new xml file from this xml. Now I need to store the first BSC id and need to check it against the other BSC ids. If both ids are same then I need to write the the contents of between the BSC id tag in a new xml file.
Re: XML parsing question
On 12-03-15 11:01 AM, Anirban Adhikary wrote: I need to create a new xml file from this xml. Now I need to store the first BSC id and need to check it against the other BSC ids. If both ids are same then I need to write the the contents of between the BSC id tag in a new xml file. What have you tried so far? -- Just my 0.0002 million dollars worth, Shawn Programming is as much about organization and communication as it is about coding. It's Mutual Aid, not fierce competition, that's the dominate force of evolution. Of course, anyone who has worked in open source already knows this. -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: XML parsing question
I am writting a following code to parse this xml but not able yo understand that why the value of $bsc_id_1 getting changed. here is my code use strict; use warnings; my $xml_file_to_read = BSC-19478.xml; my $counter = 1; my $bsc_id_1; my $bsc_id; open my $RFH,'',$xml_file_to_read or die Can't open $xml_file_to_read $!\n; while($RFH) { chomp; if (($bsc_id_1) = /BSC id=(.*?)/ and $counter == 1){ print BSC1=[$bsc_id_1]\n; next; } if (! m{/BSC} and $counter == 1) { print 1\n; next; } if (($bsc_id) = /BSC id=(.*?)/ and $counter == 0){ print LINE=[$_]\n; print BSC1=[$bsc_id_1]\n; print BSC2=[$bsc_id]\n; if ($bsc_id eq $bsc_id_1) { $bsc_id = $bsc_id_1; } } $counter = 0; print COUNTER=[$counter]\n; #exit 0; } close($RFH); and here is my output perl parse_xml.pl BSC1=[AMIBRB1] 1 1 1 1 1 1 1 1 COUNTER=[0] LINE=[BSC id=BAYHAB1] BSC1=[BAYHAB1] BSC2=[BAYHAB1] COUNTER=[0] COUNTER=[0] COUNTER=[0] COUNTER=[0] COUNTER=[0] COUNTER=[0] COUNTER=[0] COUNTER=[0] COUNTER=[0] COUNTER=[0] On Thu, Mar 15, 2012 at 8:31 PM, Anirban Adhikary anirban.adhik...@gmail.com wrote: Hi List , I have a xml file which looks like BSC id=AMIBRB1 ALPHA10/ALPHA AMRCSFR3MODE1,3,4,7/AMRCSFR3MODE AMRCSFR3THR12,16,21/AMRCSFR3THR AMRCSFR3HYST2,3,3/AMRCSFR3HYST AMRCSFR4MODE1,3,6,8/AMRCSFR4MODE AMRCSFR4THR12,17,25/AMRCSFR4THR PAGBUNDLE50/PAGBUNDLE USERDATAAMI_BRANLY_B_1/USERDATA /BSC BSC id=BAYHAB1 ALPHA10/ALPHA AMRCSFR3MODE1,3,4,7/AMRCSFR3MODE AMRCSFR3THR12,16,21/AMRCSFR3THR AMRCSFR3HYST2,3,3/AMRCSFR3HYST AMRCSFR4MODE1,3,6,8/AMRCSFR4MODE REESTON/REEST REPFACCHON/REPFACCH BCCHNORMAL0/BCCHNORMAL /BSC I need to create a new xml file from this xml. Now I need to store the first BSC id and need to check it against the other BSC ids. If both ids are same then I need to write the the contents of between the BSC id tag in a new xml file.
Re: XML parsing question
On 03/15/2012 09:11 AM, Anirban Adhikary wrote: I am writting a following code to parse this xml but not able yo understand that why the value of $bsc_id_1 getting changed. here is my code use strict; use warnings; my $xml_file_to_read = BSC-19478.xml; my $counter = 1; my $bsc_id_1; my $bsc_id; open my $RFH,'',$xml_file_to_read or die Can't open $xml_file_to_read $!\n; Writing code to parse XML is a terrible, terrible idea. There are many, many excellent modules. I happen to love XML::LibXML http://search.cpan.org/modlist/String_Language_Text_Processing/XML -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: XML parsing question
I agree with Lawrence! I am currently using two older packages called XML::SAX and XML::SAX::Expat ; they may well be a bit old-fashioned, but they work for me. Rgds, GFStC. -Original Message- From: Lawrence Statton Sent: Thursday, March 15, 2012 12:47 PM To: beginners@perl.org Cc: anirban.adhik...@gmail.com Subject: Re: XML parsing question On 03/15/2012 09:11 AM, Anirban Adhikary wrote: I am writting a following code to parse this xml but not able yo understand that why the value of $bsc_id_1 getting changed. here is my code use strict; use warnings; my $xml_file_to_read = BSC-19478.xml; my $counter = 1; my $bsc_id_1; my $bsc_id; open my $RFH,'',$xml_file_to_read or die Can't open $xml_file_to_read $!\n; Writing code to parse XML is a terrible, terrible idea. There are many, many excellent modules. I happen to love XML::LibXML http://search.cpan.org/modlist/String_Language_Text_Processing/XML -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/ -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: XML parsing question
On 12-03-15 01:32 PM, Graeme St.Clair wrote: I agree with Lawrence! I am currently using two older packages called XML::SAX and XML::SAX::Expat ; they may well be a bit old-fashioned, but they work for me. I would suggest XML::Twig -- Just my 0.0002 million dollars worth, Shawn Programming is as much about organization and communication as it is about coding. It's Mutual Aid, not fierce competition, that's the dominate force of evolution. Of course, anyone who has worked in open source already knows this. -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: XML parsing question
Hi Anirban, On Thu, 15 Mar 2012 20:41:31 +0530 Anirban Adhikary anirban.adhik...@gmail.com wrote: I am writting a following code to parse this xml but not able yo understand that why the value of $bsc_id_1 getting changed. here is my code use strict; use warnings; my $xml_file_to_read = BSC-19478.xml; my $counter = 1; my $bsc_id_1; my $bsc_id; open my $RFH,'',$xml_file_to_read or die Can't open $xml_file_to_read $!\n; while($RFH) { chomp; if (($bsc_id_1) = /BSC id=(.*?)/ and $counter == 1){ print BSC1=[$bsc_id_1]\n; next; } [SNIP] Please don't parse XML using regular expressions. Use an XML parser such as http://search.cpan.org/dist/XML-LibXML/ (of which I took over the maintenance, but I have used it beforehand, when it was maintained by other people), or a similar parser (but please avoid XML::Simple). If the XML is not too large read about its DOM (Document Object Model) capabilities and its XPath support. Regards, Shlomi Fish -- - Shlomi Fish http://www.shlomifish.org/ UNIX Fortune Cookies - http://www.shlomifish.org/humour/fortunes/ Skill without imagination is craftsmanship and gives us many useful objects such as wickerwork picnic baskets. Imagination without skill gives us modern art.— Tom Stoppard Please reply to list if it's a mailing list post - http://shlom.in/reply . -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
RE: Parsing Question
Hi Tim: As you indicate a line return is missing, in the original email: # print this information to the screen print $current_block_hostname:$current_state\n; # since were finished with this hoststatus # block we can reset our $we_are_inside_hoststatus_block Should show up as: # print this information to the screen print $current_block_hostname:$current_state\n; # since were finished with this hoststatus # block we can reset our $we_are_inside_hoststatus_block Since $we_are_inside_hoststatus_block was not intended here to start a statement. Including $we_are_inside_hoststatus_block in the print, will not have much value as the field is either a 1, 0 or undef (1 at this point, if it were undef, we'd get a warning). Sincerely, David Kronheim Production Support Tier II Gateway Error Correction, VZ450 EDI, EDI Billing, Metakey/LIA 484-213-1315 From: timothy adigun [2teezp...@gmail.com] Sent: Wednesday, February 01, 2012 2:11 PM To: jbiskofski Cc: Brandon Phelps; beginners@perl.org Subject: Re: Parsing Question Hi jbiskofski, This script will not work WHY? -- Scalar found where operator expected at . [ Please Check ] line 72, near $we_are_inside_hoststatus_block .. This communication is confidential. Frontier only sends and receives email on the basis of the terms set out at http://www.frontier.com/email_disclaimer. -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: Parsing Question
On 31/01/2012 22:43, Brandon Phelps wrote: Hello all, I am attempting to parse a Nagios status.dat file and am curious about what the most efficient way to do this would be. I'm sure I could come up with something but it would be very convoluted and I'm sure there is a better way. Below is a sample of the file. The sections I am interested in are the hoststatus sections. Any other section I want to simply ignore. Within the hoststatus sections are a few lines I am looking for: host_name=whatever and current_state=whatever, I'd simply like to perform a task based on these whatever's. For example, output lines such as: some_host:1 another_host:0 Where some_host and another_host are host_name's from the file, and 1 and 0 are current_state's for the corresponding host. Any pointers or examples would be appreciated! Here is a sample of the file: [snip data] Thanks, Brandon Hi Brandon The program below seems to do what you require. Hope it helps. Rob use strict; use warnings; open my $fh, '', 'status.dat' or die $!; my $hoststatus; my %data; while ($fh) { $hoststatus++ if /\bhoststatus\s*\{/; next unless $hoststatus; if (/\}/) { print $data{host_name}:$data{current_state}\n; %data = (); $hoststatus = 0; } elsif (/(\w+)=(.*\S)/) { $data{$1} = $2; } } -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: Parsing Question
Thanks everyone for the great ideas. After I implemented the solution(s) you guys proposed I stumbled upon Nagios::Object (http://search.cpan.org/~duncs/Nagios-Object-0.21.16/). I did learn a few things from your ideas though so I am grateful none the less! I recommend anyone working with Nagios check out the modules above as they seem to be fairly powerful! Thanks again for your replies, Brandon On 02/02/2012 06:31 AM, Rob Dixon wrote: On 31/01/2012 22:43, Brandon Phelps wrote: Hello all, I am attempting to parse a Nagios status.dat file and am curious about what the most efficient way to do this would be. I'm sure I could come up with something but it would be very convoluted and I'm sure there is a better way. Below is a sample of the file. The sections I am interested in are the hoststatus sections. Any other section I want to simply ignore. Within the hoststatus sections are a few lines I am looking for: host_name=whatever and current_state=whatever, I'd simply like to perform a task based on these whatever's. For example, output lines such as: some_host:1 another_host:0 Where some_host and another_host are host_name's from the file, and 1 and 0 are current_state's for the corresponding host. Any pointers or examples would be appreciated! Here is a sample of the file: [snip data] Thanks, Brandon Hi Brandon The program below seems to do what you require. Hope it helps. Rob use strict; use warnings; open my $fh, '', 'status.dat' or die $!; my $hoststatus; my %data; while ($fh) { $hoststatus++ if /\bhoststatus\s*\{/; next unless $hoststatus; if (/\}/) { print $data{host_name}:$data{current_state}\n; %data = (); $hoststatus = 0; } elsif (/(\w+)=(.*\S)/) { $data{$1} = $2; } } -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
RE: Parsing Question
Brandon, I took most of your comments and sample data and put it in the following program. Taking the data out of the program and parsing it from files and directories, might be a good exercise for you. Generally variables are best declared close to where they are first used. Since the scope of where $host is first used, is a different scope (using my) from where $state is first used. I declared them together, in an outer scope for consistency and flexibility (of the code). I had better whitespace in the program editor than in the email editor, that again is something you can adjust with blank lines and tabs. Let us know if any questions. #!/usr/bin/perl use strict; use warnings; use 5.012; # this script requires Perl 5.12 or greater # parse_nagios.pl =begin comment I am attempting to parse a Nagios status.dat file. The sections I am interested in are the hoststatus sections. Any other section I want to simply ignore. Within the hoststatus sections are a few lines I am looking for: host_name=whatever and current_state=whatever, I'd simply like to perform a task based on these whatever's. For example, output lines such as: some_host:1 another_host:0 Where some_host and another_host are host_name's from the file, and 1 and 0 are current_state's for the corresponding host. =end comment =cut local $/ = hoststatus {; # change input record separator, start where interested in. my ($host,$state); while( DATA ) { # stop at end of section at } my $end = index($_, }) ; my $section = substr($_, 0, $end) ; # section loses } ; # split section up by lines. my @lines=split /\n/, $section ; for my $line (@lines) { given ($line) { when (/host_name=(.*)/) { $host = $1 ; } when (/current_state=(.*)/) { $state = $1 ; say $host:$state ; } } } } __DATA__ info { created=1328049467 version=3.2.3 last_update_check=1328014790 update_available=1 last_version=3.2.3 new_version=3.3.1 } programstatus { modified_host_attributes=0 modified_service_attributes=0 nagios_pid=1370 daemon_mode=1 (lots of stuff) } hoststatus { host_name=some_host modified_attributes=0 check_command=check-host-alive check_period= notification_period=24x7 check_interval=5.00 retry_interval=1.00 event_handler= has_been_checked=1 should_be_scheduled=1 check_execution_time=0.012 check_latency=0.246 check_type=0 current_state=1 last_hard_state=0 last_event_id=0 current_event_id=0 current_problem_id=0 last_problem_id=0 plugin_output=OK - 10.1.1.1.1: rta 1.822ms, lost 0% long_plugin_output= performance_data=rta=1.822ms;3000.000;5000.000;0; pl=0%;80;100;; rtmax=1.822ms rtmin=1.822ms last_check=1328049317 next_check=1328049627 check_options=0 current_attempt=1 max_attempts=10 state_type=1 last_state_change=1328047050 last_hard_state_change=1328047050 last_time_up=1328049327 last_time_down=0 last_time_unreachable=0 last_notification=0 next_notification=0 no_more_notifications=0 current_notification_number=0 current_notification_id=0 notifications_enabled=1 problem_has_been_acknowledged=0 acknowledgement_type=0 active_checks_enabled=1 passive_checks_enabled=1 event_handler_enabled=1 flap_detection_enabled=1 failure_prediction_enabled=1 process_performance_data=1 obsess_over_host=1 last_update=1328049467 is_flapping=0 percent_state_change=0.00 scheduled_downtime_depth=0 } hoststatus { host_name=another_host modified_attributes=0 check_command=check-host-alive check_period= notification_period=24x7 check_interval=5.00 retry_interval=1.00 event_handler= has_been_checked=1 should_be_scheduled=1 check_execution_time=10.011 check_latency=0.268 check_type=0 current_state=0 last_hard_state=0 last_event_id=7 current_event_id=8 current_problem_id=3 last_problem_id=1 plugin_output=CRITICAL - 10.1.1.2: rta nan, lost 100% long_plugin_output= performance_data=rta=0.000ms;3000.000;5000.000;0; pl=100%;80;100;; rtmax=0.000ms rtmin=0.000ms last_check=1328049417 next_check=1328049497 check_options=0 current_attempt=3 max_attempts=10 state_type=0 last_state_change=1328049437 last_hard_state_change=1328049057 last_time_up=1328049057
Re: Parsing Question
Just my $0.02... can't help offering a slight rewrite of David's great program. Now it's runnable on 5.010 and earlier, and should give out some warnings if hoststatus sections are somehow corrupt: $|++; # comment it out if you don't need to buffer the output my $section_started; my ($host, $state); while(DATA) { if ($section_started) { $host = $1, next if /host_name=(\w+)/; $state = $1, next if /current_state=(\d+)/; if (/^\s*}\s*$/) { print defined $host defined $state ? $host:$state\n : Invalid section started at $section_started\n; $section_started = 0; } } else { $section_started = $., ($host, $state) = () if /hoststatus\s*{/; } } -- iD 2012/2/1 Brandon Phelps bphe...@gls.com Thanks a ton David, This will definitely help! Not able to try it now but I'll give it a shot first thing tomorrow. -Brandon -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: Parsing Question
Hey Brandon Here is a solution to this problem. It is purposely really long. It takes the simplest most understandable solution. If you have questions about it let me know. #!/usr/local/bin/perl # always a good idea, forces scope to if/for/foreach/while blocks use strict; # open the file, into a file handle called $RR - die with sad face if unable # to open file open my $RR, '', 'nagios.dat' || die 'unable to open nagios.dat :('; # we need to know if were inside a 'hoststatus' block or not # this variable keeps track of that my $we_are_inside_hoststatus_block = 0; # the logic is to set $we_are_inside_hoststatus_block to 1 ( true ) # when we see the hoststatus block begins and then set it to 0 ( false ) # when the block is done # once were inside a hoststatus block were going to save the actual hostname # in this variable my $current_block_hostname; # read file line by line while ($RR) { # each line coming into this block of code is automatically # called $_ by perl, were going to rename it to $line # to make the example clearer my $line = $_; # each line thats coming in has a \n ( carriage return - new line) # at the end - we dont need that. chomp() removes it chomp $line; # theres two possible scenarios # 1 . were outside a hoststatus block # 2 . were inside a hoststatus block if ($we_are_inside_hoststatus_block) { # theres two possible scenarios inside of here # 1 . we already know the hostname of this hoststatus block # 2 . we do not if ($current_block_hostname) { # case 1 # were inside a hoststatus block # and we know what host_name it is for # all we need is the current_state # read the big comment in the else{} # block below to know what this is doing # \d+ means one or more numbers next unless $line =~ /\s+current_state=(\d+)/; my $current_state = $1; # we have everything we need # host_name and current_state and were in a # host status block - all we need to do is # print this information to the screen print $current_block_hostname:$current_state\n; # since were finished with this hoststatus # block we can reset our $we_are_inside_hoststatus_block # and $current_block_hostname variables # so the script starts looking for a new # hoststatus block to process $we_are_inside_hoststatus_block = undef; $current_block_hostname = undef; next; } else { # case 2 # were inside a hostsatus block but we still # dont know what hostname its for # # we dont care about any line unless # it matches the regular expression : # one or more spaces # 'host_name=' # \S+ means : something thats not whitespace # the parentheses mean we want to capture # the value between them # perl will automatically call the first # captured value $1, the second one $2 # so on and so forth next unless $line =~ /\s+host_name=(\S+)/; # cool we have the hostname of this hoststatus # block $current_block_hostname = $1; # go to the next line of the file next; } } else { # we are not inside a hoststatus block # in this case we dont care about any of these lines # unless its a line that STARTS a hoststatus block # does the line match the regular expression that # informs us we are starting a hoststatus block ? # ^ means beginning of line # \s+ means one or more spaces # so were looking for a line that begins with # 'hoststatus' has one or more spaces and then has a '{' if ( $line =~ /^hoststatus\s+{/ ) { # were inside a new hoststatus block $we_are_inside_hoststatus_block = 1; } } } close $RR; == Peace it in, peace it out peace it inside out. - Jose from
Re: Parsing Question
Hi jbiskofski, This script will not work WHY? -- Scalar found where operator expected at . [ Please Check ] line 72, near $we_are_inside_hoststatus_block .. On Wed, Feb 1, 2012 at 6:38 PM, jbiskofski jbiskof...@gmail.com wrote: Hey Brandon Here is a solution to this problem. It is purposely really long. It takes the simplest most understandable solution. If you have questions about it let me know. #!/usr/local/bin/perl # always a good idea, forces scope to if/for/foreach/while blocks use strict; # open the file, into a file handle called $RR - die with sad face if unable # to open file NOTE HERE ### open my $RR, '', 'nagios.dat' || die 'unable to open nagios.dat :('; Please check = I think the line above would be better as: open (my $RR, '', 'nagios.dat') || die 'unable to open nagios.dat :('; OR open my $RR, '', 'nagios.dat' or die 'unable to open nagios.dat :('; # we need to know if were inside a 'hoststatus' block or not # this variable keeps track of that my $we_are_inside_hoststatus_block = 0; # the logic is to set $we_are_inside_hoststatus_block to 1 ( true ) # when we see the hoststatus block begins and then set it to 0 ( false ) # when the block is done # once were inside a hoststatus block were going to save the actual hostname # in this variable my $current_block_hostname; # read file line by line while ($RR) { # each line coming into this block of code is automatically # called $_ by perl, were going to rename it to $line # to make the example clearer my $line = $_; # each line thats coming in has a \n ( carriage return - new line) # at the end - we dont need that. chomp() removes it chomp $line; # theres two possible scenarios # 1 . were outside a hoststatus block # 2 . were inside a hoststatus block if ($we_are_inside_hoststatus_block) { # theres two possible scenarios inside of here # 1 . we already know the hostname of this hoststatus block # 2 . we do not if ($current_block_hostname) { # case 1 # were inside a hoststatus block # and we know what host_name it is for # all we need is the current_state # read the big comment in the else{} # block below to know what this is doing # \d+ means one or more numbers next unless $line =~ /\s+current_state=(\d+)/; my $current_state = $1; # we have everything we need # host_name and current_state and were in a # host status block - all we need to do is # print this information to the screen print $current_block_hostname:$current_state\n; I think the print function should also have $we_are_inside_hoststatus_block covered. Therefore, the ; should have been after $we_are_inside_hoststatus_block. # since were finished with this hoststatus # block we can reset our $we_are_inside_hoststatus_block == HERE Please check # and $current_block_hostname variables # so the script starts looking for a new # hoststatus block to process $we_are_inside_hoststatus_block = undef; $current_block_hostname = undef; next; } else { # case 2 # were inside a hostsatus block but we still # dont know what hostname its for # # we dont care about any line unless # it matches the regular expression : # one or more spaces # 'host_name=' # \S+ means : something thats not whitespace # the parentheses mean we want to capture # the value between them # perl will automatically call the first # captured value $1, the second one $2 # so on and so forth next unless $line =~ /\s+host_name=(\S+)/; # cool we have the hostname of this hoststatus # block $current_block_hostname = $1; # go to the next line of the file next; } } else { # we are not inside a hoststatus block # in this case we dont care about any of
Re: Parsing Question
Timothy Could it be that when you copy pasted the script the line wrap got messed up? It works fine for me. Im using perl 5.12.3 Your comment about the open statement is OK. I guess it really comes down to style. I was trying to write something clear that Brandon could improve upon. Here is a pastebin of the same script : http://pastebin.com/h8cebCD7 - Jose from Mexico On Wed, Feb 1, 2012 at 1:11 PM, timothy adigun 2teezp...@gmail.com wrote: Hi jbiskofski, This script will not work WHY? -- Scalar found where operator expected at . [ Please Check ] line 72, near $we_are_inside_hoststatus_block .. On Wed, Feb 1, 2012 at 6:38 PM, jbiskofski jbiskof...@gmail.com wrote: Hey Brandon Here is a solution to this problem. It is purposely really long. It takes the simplest most understandable solution. If you have questions about it let me know. #!/usr/local/bin/perl # always a good idea, forces scope to if/for/foreach/while blocks use strict; # open the file, into a file handle called $RR - die with sad face if unable # to open file NOTE HERE ### open my $RR, '', 'nagios.dat' || die 'unable to open nagios.dat :('; Please check = I think the line above would be better as: open (my $RR, '', 'nagios.dat') || die 'unable to open nagios.dat :('; OR open my $RR, '', 'nagios.dat' or die 'unable to open nagios.dat :('; # we need to know if were inside a 'hoststatus' block or not # this variable keeps track of that my $we_are_inside_hoststatus_block = 0; # the logic is to set $we_are_inside_hoststatus_block to 1 ( true ) # when we see the hoststatus block begins and then set it to 0 ( false ) # when the block is done # once were inside a hoststatus block were going to save the actual hostname # in this variable my $current_block_hostname; # read file line by line while ($RR) { # each line coming into this block of code is automatically # called $_ by perl, were going to rename it to $line # to make the example clearer my $line = $_; # each line thats coming in has a \n ( carriage return - new line) # at the end - we dont need that. chomp() removes it chomp $line; # theres two possible scenarios # 1 . were outside a hoststatus block # 2 . were inside a hoststatus block if ($we_are_inside_hoststatus_block) { # theres two possible scenarios inside of here # 1 . we already know the hostname of this hoststatus block # 2 . we do not if ($current_block_hostname) { # case 1 # were inside a hoststatus block # and we know what host_name it is for # all we need is the current_state # read the big comment in the else{} # block below to know what this is doing # \d+ means one or more numbers next unless $line =~ /\s+current_state=(\d+)/; my $current_state = $1; # we have everything we need # host_name and current_state and were in a # host status block - all we need to do is # print this information to the screen print $current_block_hostname:$current_state\n; I think the print function should also have $we_are_inside_hoststatus_block covered. Therefore, the ; should have been after $we_are_inside_hoststatus_block. # since were finished with this hoststatus # block we can reset our $we_are_inside_hoststatus_block == HERE Please check # and $current_block_hostname variables # so the script starts looking for a new # hoststatus block to process $we_are_inside_hoststatus_block = undef; $current_block_hostname = undef; next; } else { # case 2 # were inside a hostsatus block but we still # dont know what hostname its for # # we dont care about any line unless # it matches the regular expression : # one or more spaces # 'host_name=' # \S+ means : something thats not whitespace # the parentheses mean we want to capture # the value between them # perl will automatically call the first # captured value $1, the second one $2 # so on and so forth
Re: Parsing Question
On 2/1/12 Wed Feb 1, 2012 11:24 AM, jbiskofski jbiskof...@gmail.com scribbled: Your comment about the open statement is OK. I guess it really comes down to style. I was trying to write something clear that Brandon could improve upon. It is not simply a matter of style. Because of operator precedence, the statement open my $RR, '', 'nagios.dat' || die 'unable to open nagios.dat :('; will be parsed as open my $RR, '', ('nagios.dat' || die 'unable to open nagios.dat :('); because the precedence of '||' is higher than that of ','. Because the scalar value 'nagios.dat' is always true, the above statement is equivalent to the following: open my $RR, '', 'nagios.dat'; In other words, the die will never get executed, regardless of the success or failure of the open. So you either need to place parentheses around the open arguments: open( my $RR, '', 'nagios.dat') || die 'unable to open nagios.dat :('; or use the lower-precedent 'or' operator: open my $RR, '', 'nagios.dat' or die 'unable to open nagios.dat :('; as Timothy has suggested. For operator precedence, see 'perldoc perlop'. -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: Parsing Question
ah - i get it now. thanks. On Wed, Feb 1, 2012 at 3:05 PM, Jim Gibson jimsgib...@gmail.com wrote: On 2/1/12 Wed Feb 1, 2012 11:24 AM, jbiskofski jbiskof...@gmail.com scribbled: Your comment about the open statement is OK. I guess it really comes down to style. I was trying to write something clear that Brandon could improve upon. It is not simply a matter of style. Because of operator precedence, the statement open my $RR, '', 'nagios.dat' || die 'unable to open nagios.dat :('; will be parsed as open my $RR, '', ('nagios.dat' || die 'unable to open nagios.dat :('); because the precedence of '||' is higher than that of ','. Because the scalar value 'nagios.dat' is always true, the above statement is equivalent to the following: open my $RR, '', 'nagios.dat'; In other words, the die will never get executed, regardless of the success or failure of the open. So you either need to place parentheses around the open arguments: open( my $RR, '', 'nagios.dat') || die 'unable to open nagios.dat :('; or use the lower-precedent 'or' operator: open my $RR, '', 'nagios.dat' or die 'unable to open nagios.dat :('; as Timothy has suggested. For operator precedence, see 'perldoc perlop'. -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Parsing Question
Hello all, I am attempting to parse a Nagios status.dat file and am curious about what the most efficient way to do this would be. I'm sure I could come up with something but it would be very convoluted and I'm sure there is a better way. Below is a sample of the file. The sections I am interested in are the hoststatus sections. Any other section I want to simply ignore. Within the hoststatus sections are a few lines I am looking for: host_name=whatever and current_state=whatever, I'd simply like to perform a task based on these whatever's. For example, output lines such as: some_host:1 another_host:0 Where some_host and another_host are host_name's from the file, and 1 and 0 are current_state's for the corresponding host. Any pointers or examples would be appreciated! Here is a sample of the file: info { created=1328049467 version=3.2.3 last_update_check=1328014790 update_available=1 last_version=3.2.3 new_version=3.3.1 } programstatus { modified_host_attributes=0 modified_service_attributes=0 nagios_pid=1370 daemon_mode=1 (lots of stuff) } hoststatus { host_name=some_host modified_attributes=0 check_command=check-host-alive check_period= notification_period=24x7 check_interval=5.00 retry_interval=1.00 event_handler= has_been_checked=1 should_be_scheduled=1 check_execution_time=0.012 check_latency=0.246 check_type=0 current_state=1 last_hard_state=0 last_event_id=0 current_event_id=0 current_problem_id=0 last_problem_id=0 plugin_output=OK - 10.1.1.1.1: rta 1.822ms, lost 0% long_plugin_output= performance_data=rta=1.822ms;3000.000;5000.000;0; pl=0%;80;100;; rtmax=1.822ms rtmin=1.822ms last_check=1328049317 next_check=1328049627 check_options=0 current_attempt=1 max_attempts=10 state_type=1 last_state_change=1328047050 last_hard_state_change=1328047050 last_time_up=1328049327 last_time_down=0 last_time_unreachable=0 last_notification=0 next_notification=0 no_more_notifications=0 current_notification_number=0 current_notification_id=0 notifications_enabled=1 problem_has_been_acknowledged=0 acknowledgement_type=0 active_checks_enabled=1 passive_checks_enabled=1 event_handler_enabled=1 flap_detection_enabled=1 failure_prediction_enabled=1 process_performance_data=1 obsess_over_host=1 last_update=1328049467 is_flapping=0 percent_state_change=0.00 scheduled_downtime_depth=0 } hoststatus { host_name=another_host modified_attributes=0 check_command=check-host-alive check_period= notification_period=24x7 check_interval=5.00 retry_interval=1.00 event_handler= has_been_checked=1 should_be_scheduled=1 check_execution_time=10.011 check_latency=0.268 check_type=0 current_state=0 last_hard_state=0 last_event_id=7 current_event_id=8 current_problem_id=3 last_problem_id=1 plugin_output=CRITICAL - 10.1.1.2: rta nan, lost 100% long_plugin_output= performance_data=rta=0.000ms;3000.000;5000.000;0; pl=100%;80;100;; rtmax=0.000ms rtmin=0.000ms last_check=1328049417 next_check=1328049497 check_options=0 current_attempt=3 max_attempts=10 state_type=0 last_state_change=1328049437 last_hard_state_change=1328049057 last_time_up=1328049057 last_time_down=1328049437 last_time_unreachable=0 last_notification=0 next_notification=0 no_more_notifications=0 current_notification_number=0 current_notification_id=0 notifications_enabled=1 problem_has_been_acknowledged=0 acknowledgement_type=0 active_checks_enabled=1 passive_checks_enabled=1 event_handler_enabled=1 flap_detection_enabled=1 failure_prediction_enabled=1 process_performance_data=1 obsess_over_host=1 last_update=1328049467 is_flapping=0 percent_state_change=17.30 scheduled_downtime_depth=0 } servicestatus { host_name=some_host service_description=PING modified_attributes=0 check_command=check_ping!7000.0,40%!9000.0,70% check_period=24x7 notification_period=24x7 check_interval=5.00 (lots more stuff...) } (file has lots more, but excluded here for brevity) Thanks, Brandon -- To unsubscribe, e-mail:
Re: Parsing Question
Thanks a ton David, This will definitely help! Not able to try it now but I'll give it a shot first thing tomorrow. -Brandon On 1/31/2012 8:15 PM, Kronheim, David (Contr) wrote: Brandon, I took most of your comments and sample data and put it in the following program. Taking the data out of the program and parsing it from files and directories, might be a good exercise for you. Generally variables are best declared close to where they are first used. Since the scope of where $host is first used, is a different scope (using my) from where $state is first used. I declared them together, in an outer scope for consistency and flexibility (of the code). I had better whitespace in the program editor than in the email editor, that again is something you can adjust with blank lines and tabs. Let us know if any questions. #!/usr/bin/perl use strict; use warnings; use 5.012; # this script requires Perl 5.12 or greater # parse_nagios.pl =begin comment I am attempting to parse a Nagios status.dat file. The sections I am interested in are the hoststatus sections. Any other section I want to simply ignore. Within the hoststatus sections are a few lines I am looking for: host_name=whatever and current_state=whatever, I'd simply like to perform a task based on these whatever's. For example, output lines such as: some_host:1 another_host:0 Where some_host and another_host are host_name's from the file, and 1 and 0 are current_state's for the corresponding host. =end comment =cut local $/ = hoststatus {; # change input record separator, start where interested in. my ($host,$state); while(DATA ) { # stop at end of section at } my $end = index($_, }) ; my $section = substr($_, 0, $end) ; # section loses } ; # split section up by lines. my @lines=split /\n/, $section ; for my $line (@lines) { given ($line) { when (/host_name=(.*)/) { $host = $1 ; } when (/current_state=(.*)/) { $state = $1 ; say $host:$state ; } } } } __DATA__ info { created=1328049467 version=3.2.3 last_update_check=1328014790 update_available=1 last_version=3.2.3 new_version=3.3.1 } programstatus { modified_host_attributes=0 modified_service_attributes=0 nagios_pid=1370 daemon_mode=1 (lots of stuff) } hoststatus { host_name=some_host modified_attributes=0 check_command=check-host-alive check_period= notification_period=24x7 check_interval=5.00 retry_interval=1.00 event_handler= has_been_checked=1 should_be_scheduled=1 check_execution_time=0.012 check_latency=0.246 check_type=0 current_state=1 last_hard_state=0 last_event_id=0 current_event_id=0 current_problem_id=0 last_problem_id=0 plugin_output=OK - 10.1.1.1.1: rta 1.822ms, lost 0% long_plugin_output= performance_data=rta=1.822ms;3000.000;5000.000;0; pl=0%;80;100;; rtmax=1.822ms rtmin=1.822ms last_check=1328049317 next_check=1328049627 check_options=0 current_attempt=1 max_attempts=10 state_type=1 last_state_change=1328047050 last_hard_state_change=1328047050 last_time_up=1328049327 last_time_down=0 last_time_unreachable=0 last_notification=0 next_notification=0 no_more_notifications=0 current_notification_number=0 current_notification_id=0 notifications_enabled=1 problem_has_been_acknowledged=0 acknowledgement_type=0 active_checks_enabled=1 passive_checks_enabled=1 event_handler_enabled=1 flap_detection_enabled=1 failure_prediction_enabled=1 process_performance_data=1 obsess_over_host=1 last_update=1328049467 is_flapping=0 percent_state_change=0.00 scheduled_downtime_depth=0 } hoststatus { host_name=another_host modified_attributes=0 check_command=check-host-alive check_period= notification_period=24x7 check_interval=5.00 retry_interval=1.00 event_handler= has_been_checked=1 should_be_scheduled=1 check_execution_time=10.011 check_latency=0.268 check_type=0 current_state=0 last_hard_state=0 last_event_id=7 current_event_id=8 current_problem_id=3 last_problem_id=1 plugin_output=CRITICAL - 10.1.1.2: rta nan, lost 100% long_plugin_output= performance_data=rta=0.000ms;3000.000;5000.000;0; pl=100%;80;100;; rtmax=0.000ms
Re: Yet another parsing question
D. Bolliger wrote: Gallagher, Tim F (NE) am Donnerstag, 14. Dezember 2006 15:29: Lets say that I have a list of data that have a few things in common, ie this is a 1 test to see 2 what is happening 3 to the state of the 4 country all work 1 and no 2 play makes 3 jack a dull boy 4 how 1 much wood 2 could a wood 3 chuck 4 chuck so I want to grab all data between 1 - 2 and 3 - 4 2 different variables, can this be done? Yes :-) Use capturing parenthesis for that, see perldoc perlre Dani ($var1, $var2) = $str =~ /1(.*?)2.*?3(.*?)4/; -- BR Eugene Kosov -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/ http://learn.perl.org/first-response
Yet another parsing question
Lets say that I have a list of data that have a few things in common, ie this is a 1 test to see 2 what is happening 3 to the state of the 4 country all work 1 and no 2 play makes 3 jack a dull boy 4 how 1 much wood 2 could a wood 3 chuck 4 chuck so I want to grab all data between 1 - 2 and 3 - 4 2 different variables, can this be done? Thanks. -T
Re: Yet another parsing question
Gallagher, Tim F (NE) am Donnerstag, 14. Dezember 2006 15:29: Lets say that I have a list of data that have a few things in common, ie this is a 1 test to see 2 what is happening 3 to the state of the 4 country all work 1 and no 2 play makes 3 jack a dull boy 4 how 1 much wood 2 could a wood 3 chuck 4 chuck so I want to grab all data between 1 - 2 and 3 - 4 2 different variables, can this be done? Yes :-) Use capturing parenthesis for that, see perldoc perlre Dani -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/ http://learn.perl.org/first-response
re: File Parsing Question
Hello, I'm trying to figure out how to read multiple lines from a file at once for parsing. For example,, If the file contained the following: input file Line 1 Line 2 Line 3 Line 4 Line 5 Line 6 Line 7 Line 8 I want to read in lines 1-4 for processing then during the next iteration read lines 5-8. Could someone give me a could starting place? -- William Black [EMAIL PROTECTED]
Re: File Parsing Question
William Black wrote: Hello, I'm trying to figure out how to read multiple lines from a file at once for parsing. For example,, If the file contained the following: input file Line 1 Line 2 Line 3 Line 4 Line 5 Line 6 Line 7 Line 8 I want to read in lines 1-4 for processing then during the next iteration read lines 5-8. Could someone give me a could starting place? I know of no other way than the hard way. #!/usr/bin/perl use strict; use warnings; use Data::Dumper; while( ! eof DATA ){ my @lines = (); for my $i ( 1 .. 4 ){ my $line = DATA; push @lines, $line; } # process @lines print Dumper [EMAIL PROTECTED]; } __END__ line 1 line 2 line 3 line 4 line 5 line 6 line 7 line 8 line 9 -- Just my 0.0002 million dollars worth, --- Shawn Probability is now one. Any problems that are left are your own. SS Heart of Gold, _The Hitchhiker's Guide to the Galaxy_ * Perl tutorials at http://perlmonks.org/?node=Tutorials * A searchable perldoc is available at http://perldoc.perl.org/ -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/ http://learn.perl.org/first-response
Re: Regex parsing question
Perl wrote: I am attempting to parse a log file that looks something like: 759033281 TE18 Vups_MsgStore constructor - add to MDBTable EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD 759033281 TE18 Vups_MsgStore AddRef=2 EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD 759033281 TE18 MSM S-REXCH-MSG-07 759033281 TE18 MSM S-REXCH-MSG-06 759033281 TE18 MSM C-REXCH-MSG-07 759033281 TE18 MSM C-REXCH-MSG-06 759033281 TE18 VUPSMAPI Vups_MailboxLogon done 0x0 759033281 TE18 MSM C-REXCH-MSG-06 759033281 TE18 MSM No timestamp for thread 759033281 TE18 MsgLog 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 (LOGFILE) { my @fields = split / /; if (/PHARWOOD/) { print $_; } } } } This loop does what you ask print if /PHARWOOD/ .. /OpenMsgStore/ while LOGFILE; 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 Vups_MsgStore constructor - add to MDBTable EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD 759033281 TE18 Vups_MsgStore AddRef=2 EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD 759033281 TE18 MSM S-REXCH-MSG-07 759033281 TE18 MSM S-REXCH-MSG-06 759033281 TE18 MSM C-REXCH-MSG-07 759033281 TE18 MSM C-REXCH-MSG-06 759033281 TE18 VUPSMAPI Vups_MailboxLogon done 0x0 759033281 TE18 MSM C-REXCH-MSG-06 759033281 TE18 MSM No timestamp for thread 759033281 TE18 MsgLog 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 (LOGFILE) { my @fields = split / /; if (/PHARWOOD/) { print $_; } } } } This loop does what you ask print if /PHARWOOD/ .. /OpenMsgStore/ while LOGFILE; 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
Rob Dixon wrote: Perl wrote: I am attempting to parse a log file that looks something like: 759033281 TE18 Vups_MsgStore constructor - add to MDBTable EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD 759033281 TE18 Vups_MsgStore AddRef=2 EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD 759033281 TE18 MSM S-REXCH-MSG-07 759033281 TE18 MSM S-REXCH-MSG-06 759033281 TE18 MSM C-REXCH-MSG-07 759033281 TE18 MSM C-REXCH-MSG-06 759033281 TE18 VUPSMAPI Vups_MailboxLogon done 0x0 759033281 TE18 MSM C-REXCH-MSG-06 759033281 TE18 MSM No timestamp for thread 759033281 TE18 MsgLog 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 (LOGFILE) { my @fields = split / /; if (/PHARWOOD/) { print $_; } } } } This loop does what you ask print if /PHARWOOD/ .. /OpenMsgStore/ while LOGFILE; 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 (LOGFILE) { 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
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 Vups_MsgStore constructor - add to MDBTable EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD 759033281 TE18 Vups_MsgStore AddRef=2 EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD 759033281 TE18 MSM S-REXCH-MSG-07 759033281 TE18 MSM S-REXCH-MSG-06 759033281 TE18 MSM C-REXCH-MSG-07 759033281 TE18 MSM C-REXCH-MSG-06 759033281 TE18 VUPSMAPI Vups_MailboxLogon done 0x0 759033281 TE18 MSM C-REXCH-MSG-06 759033281 TE18 MSM No timestamp for thread 759033281 TE18 MsgLog 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 (LOGFILE) { my @fields = split / /; if (/PHARWOOD/) { print $_; } } } } This loop does what you ask print if /PHARWOOD/ .. /OpenMsgStore/ while LOGFILE; 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 (LOGFILE) { 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]
Regex parsing question
I am attempting to parse a log file that looks something like: 759033281 TE18 Vups_MsgStore constructor - add to MDBTable EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD 759033281 TE18 Vups_MsgStore AddRef=2 EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD 759033281 TE18 MSM S-REXCH-MSG-07 759033281 TE18 MSM S-REXCH-MSG-06 759033281 TE18 MSM C-REXCH-MSG-07 759033281 TE18 MSM C-REXCH-MSG-06 759033281 TE18 VUPSMAPI Vups_MailboxLogon done 0x0 759033281 TE18 MSM C-REXCH-MSG-06 759033281 TE18 MSM No timestamp for thread 759033281 TE18 MsgLog 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 (LOGFILE) { my @fields = split / /; if (/PHARWOOD/) { print $_; } } } }
Re: Regex parsing question
Perl wrote: I am attempting to parse a log file that looks something like: 759033281 TE18 Vups_MsgStore constructor - add to MDBTable EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD 759033281 TE18 Vups_MsgStore AddRef=2 EX:/O=MSGENG/OU=EUROPE/CN=RECIPIENTS/CN=PHARWOOD 759033281 TE18 MSM S-REXCH-MSG-07 759033281 TE18 MSM S-REXCH-MSG-06 759033281 TE18 MSM C-REXCH-MSG-07 759033281 TE18 MSM C-REXCH-MSG-06 759033281 TE18 VUPSMAPI Vups_MailboxLogon done 0x0 759033281 TE18 MSM C-REXCH-MSG-06 759033281 TE18 MSM No timestamp for thread 759033281 TE18 MsgLog 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]
Parsing question
We are integrating with the Yahoo storefront for some customers, and I am having a problem accessing some of the data elements within the data stream. This is a dump of the raw information dumped by my program: Bill-Address1 = 5575 North Service Road Bill-Address2 = 4th Floor Bill-City = Burlington Bill-Country = US United States Bill-Email = [EMAIL PROTECTED] Bill-Firstname = Carlin Bill-Lastname = Anderson Bill-Name = Carlin Anderson Bill-Phone = 905-111- Bill-State = OH Bill-Zip = 13433 Card-Expiry = 4/2003 Card-Name = Visa Card-Number = 4111 Comments = Coupon-Description = Coupon-Value = Currency = USD Date = Fri Oct 19 15:07:35 2001 GMT Gift-Wrap = on Gift-Wrap-Charge = 15 Gift-Wrap-Message = A test gift message ID = edig-536 Item-Code-1 = 13-330039 Item-Count = 1 Item-Description-1 = Home Audio System Adapter Cable Item-Id-1 = 13-830053 Item-Quantity-1 = 3 Item-Taxable-1 = YES Item-Unit-Price-1 = 4.95 Item-Url-1 = http://store.yahoo.com/ Numeric-Time = 1003504055 Ship-Address1 = 5575 North Service Road Ship-Address2 = 4th Floor Ship-City = Burlington Ship-Country = US United States Ship-Firstname = Carlin Ship-Lastname = Anderson Ship-Name = Carlin Anderson Ship-Phone = 905-111- Ship-State = OH Ship-Zip = 13433 Shipping = Next Day Air Shipping-Charge = 19.95 Space-Id = Store-Id = edig Store-Name = eDigital Tax-Charge = 0.00 Total = 49.80 And here is the relevant segment of my program: #!/usr/perl5/bin/perl require 5.001; use strict; use CGI; use DBI; use File::Copy; if ($ENV{'REQUEST_METHOD'} ne POST) { die(Expecting a POST, bailing); } my $o; read(STDIN,$o,$ENV{'CONTENT_LENGTH'}); my %o; for (split(//,$o)) { $_ =~ s/\+/ /g; my($key,$val) = split(/=/,$_,2); for ($key,$val) { $_ =~ s/%([0-9a-fA-F][0-9a-fA-F])/chr(hex($1))/ge; } $o{$key} = $val; } my @items; my $i; for ($i=1; $i=$o{'Item-Count'}; $i++) { push(@items,{map {($_,$o{Item-$_-$i})} qw(Id Code Quantity Unit-Price Description Url)}); } open(RAW,/tmp/yahoo-order.raw); for (sort keys %o) { print RAW $_ = $o{$_}\n; } close(RAW); handle_order(\%o,@items); # A successful delivery is indicated by a good HTTP result code. print Status: 200 OK\n; print \n; exit(0); ## # Replace this function with something that does what you want # $info gets a hash ref of all the order fields, like Ship-Name. # @items gets an array of hash refs, one for each item. sub handle_order { my($info,@items)=@_; my $del; my $sec; my $min; my $hour; my $mday; my $mon; my $year; my $wday; my $yday; my $isdat; my $tmp; $del = \xAC; ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdat) = localtime(time); $year = $year + 1900; $mon = $mon + 1; if ($mon 10) {$mon = 0$mon;} if ($mday 10) {$mday = 0$mday;} open(OUT,/tmp/$year$mon$mday$hour$min$sec$info-{ID}.txt); print OUT H,$info-{ID},$del,$del,$info-{Date},$del,$hour,:,$min,:,$sec,$del,C RCD,$del,EDG,$del,$info-{'Shipping-Charge'},$del; if ($info-(Gift-Wrap) = on){ print OUT GIFTWRAP,$del,$info-('Gift-Wrap-Message'),$del,$info-('Gift-Wrap-Charge' ),$del,$del,$del,$del; } else { print OUT $del,$del,$del,$del,$del,$del; } print OUT $info-{'Shipping'},$del,$del,N,$del,N,$del,N,$del,$del,\n; print OUT H,$info-{'Ship-Name'},$del,$del,$info-{'Ship-Address1'},$del,$info-{'Sh ip-Address2'},$del,$info-{'Ship-City'},$del,$info-{'Ship-State'},$del,$inf o-{'Ship-Country'},$del,$info-{'Ship-Zip'},$del,$info-{'Ship-Phone'},$del ,\n; print OUT H,$info-{'Bill-Name'},$del,$del,$info-{'Bill-Address1'},$del,$info-{'Bi ll-Address2'},$del,$info-{'Bill-City'},$del,$info-{'Bill-State'},$del,$inf o-{'Bill-Country'},$del,$info-{'Bill-Zip'},$del,$info-{'Bill-Phone'},$del ,$info-{'Bill-Email'},\n; print OUT H,$info-{'Tax-Charge'},$del,$info-{'Total'},$del,$info-{'Card-Name'},$d el,$info-{'Card-Number'},$del,$info-{'Card-Expiry'},\n; close(OUT); } My problem is when I try to access the Gift-Wrap elements, the program just dies where I after the first print to OUT. I have tried everything I know of, but I am relatively new to this. Any help would be greatly appreciated. Carlin Anderson Sr. Software Engineer APL Direct Logistics 1301 Riverplace Blvd, Suite 530 Jacksonville, FL 32207 904-858-4754 direct 904-616-6542 cell phone, pager [EMAIL PROTECTED] [EMAIL PROTECTED] -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
RE: Parsing question
-Original Message- From: Anderson, Carlin [mailto:[EMAIL PROTECTED]] Sent: Friday, October 19, 2001 2:53 PM To: '[EMAIL PROTECTED]' Subject: Parsing question We are integrating with the Yahoo storefront for some customers, and I am having a problem accessing some of the data elements within the data stream. ...(snip)... My problem is when I try to access the Gift-Wrap elements, the program just dies where I after the first print to OUT. I have tried everything I know of, but I am relatively new to this. Any help would be greatly appreciated. 1. Check server error log for error messages related to the script dying. 2. You have use CGI, but then you are trying to parse the request yourself. Don't do that. Let CGI do it. -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
[beginner] file parsing question
Sorry so lengthy but here goes: I am a Perl newbie and trying to parse a file. Depending on the tags in the data I want to parse each line a different way. I built the following program to test my process. use strict; my (@lines, $testln, @REFln); while () { chomp; testType ($_); } sub testType { $testln = $_[0]; if (/^REF/) { print I found a REF line: $testln\n; parseRef ($testln); } elsif (/^NTE/) { print I found a NTE line: $testln\n; } } sub parseREF { print Parsing line: $_[0]\n; @REFln = split (/\*/, $_[0]); print Element 1) $REFln[0] ; print 2) $REFln[1] ; print 3) $REFln[2]\n; if ($REFln[1] = SN) { print $REFln[1]: $REFln[2]\n; } else { print Not a Shipment Number, $REFln[1] type line.\n; } } Based on the input: CUR**USD REF*SN*0108106 REF*PO*cn190108106 REF*BL*cn190108106 REF*PS*JessupPA I expected to see SN: 0108106 (which I did) but I didn't expect to see SN: cn190108106 and SN: cn190108106, SN: JessupPA. I expected to see Not a Shipment Number, PO/BL/PS type line. for those. It almost seems like $REFln[1] is not being refreshed each time parseREF happens. I have written this same program in VB but I'm trying to do my parsing in Perl now . To tell you the truth I really don't have a clue why this doesn't work, so any help is much appreciated. Joel
Re: [beginner] file parsing question
Hi Joel, Did you type this in by hand? :) parseRef ($testln); sub parseREF { You would want to change one of those! Anyways.. Your problem is in this line: if ($REFln[1] = SN) { = is for assignments. You want this to be: if ($REFln[1] eq SN) { To learn more about perl operators like eq, =, and == (which is for numeric comparisons, while eq is for strings) read the perlop manual page. Cheers, Kevin On Tue, Apr 24, 2001 at 08:20:59PM -, Stout, Joel R ([EMAIL PROTECTED]) spew-ed forth: Sorry so lengthy but here goes: I am a Perl newbie and trying to parse a file. Depending on the tags in the data I want to parse each line a different way. I built the following program to test my process. use strict; my (@lines, $testln, @REFln); while () { chomp; testType ($_); } sub testType { $testln = $_[0]; if (/^REF/) { print I found a REF line: $testln\n; parseRef ($testln); } elsif (/^NTE/) { print I found a NTE line: $testln\n; } } sub parseREF { print Parsing line: $_[0]\n; @REFln = split (/\*/, $_[0]); print Element 1) $REFln[0] ; print 2) $REFln[1] ; print 3) $REFln[2]\n; if ($REFln[1] = SN) { print $REFln[1]: $REFln[2]\n; } else { print Not a Shipment Number, $REFln[1] type line.\n; } } Based on the input: CUR**USD REF*SN*0108106 REF*PO*cn190108106 REF*BL*cn190108106 REF*PS*JessupPA I expected to see SN: 0108106 (which I did) but I didn't expect to see SN: cn190108106 and SN: cn190108106, SN: JessupPA. I expected to see Not a Shipment Number, PO/BL/PS type line. for those. It almost seems like $REFln[1] is not being refreshed each time parseREF happens. I have written this same program in VB but I'm trying to do my parsing in Perl now . To tell you the truth I really don't have a clue why this doesn't work, so any help is much appreciated. Joel Writing CGI Applications with Perl - http://perlcgi-book.com -- Nuclear explosions under the Nevada desert? What the f*ck are we testing for? We already know the sh*t blows up. -- Frank Zappa
Re: [beginner] file parsing question
On Tue, Apr 24, 2001 at 04:33:00PM -0400, Timothy Kimball wrote: You can avoid this by always writing comparisons with the constant (if there is one) on the left-hand side: if (SN eq $REFln) but I rarely see people actually do that. I think that's because it feels so unnatural and looks so ugly ;-) -- Paul Johnson - [EMAIL PROTECTED] http://www.pjcj.net
Re: [beginner] file parsing question
--- Timothy Kimball [EMAIL PROTECTED] wrote: Ah, yes, one of the most frustrating bugs in the world: : if ($REFln[1] = SN) { This *assigns* the value SN to $REFln[1]. What you want to do is *test* it. String comparisons in Perl are done with eq (and numeric comparisons with ==). So you want this: if ($REFln eq SN) { You can avoid this by always writing comparisons with the constant (if there is one) on the left-hand side: if (SN eq $REFln) but I rarely see people actually do that. People rarely do it, btu I *HIGHLY* recommend it. This way, if you write if (SN = $REFln) { the compiler will shut down and warn you that you can't *do* that, and you'll probably say Oh! that should have been ==, or maybe eq It's just cleaner code. =o) __ Do You Yahoo!? Yahoo! Auctions - buy the things you want at great prices http://auctions.yahoo.com/
Re: [beginner] file parsing question
- Original Message - From: Stout, Joel R [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Tuesday, April 24, 2001 10:20 PM Subject: [beginner] file parsing question Sorry so lengthy but here goes: I am a Perl newbie and trying to parse a file. Depending on the tags in the data I want to parse each line a different way. I built the following program to test my process. use strict; my (@lines, $testln, @REFln); What is @lines for? Is doesnt seem to be used. And @REFln could be declared inside sub parseREF; where $testln is better declared locally in sub testType. It might also be more efficient to read the file one time and then process it try this: #!perl my @lines = (); foreach $line (@lines) { chomp $line; my ($element1, $element2, $element3) = split (/\*/, $line, 3); if ($element1 eq 'REF' !($element2 eq 'SN')) { print Not a Shipment Number, $element1 type $line.\n; } else { print I found a $element1 line: $line\n; } } while () { chomp; testType ($_); } sub testType { $testln = $_[0]; if (/^REF/) { print I found a REF line: $testln\n; parseRef ($testln); } elsif (/^NTE/) { print I found a NTE line: $testln\n; } } sub parseREF { print Parsing line: $_[0]\n; @REFln = split (/\*/, $_[0]); print Element 1) $REFln[0] ; print 2) $REFln[1] ; print 3) $REFln[2]\n; if ($REFln[1] = SN) { print $REFln[1]: $REFln[2]\n; } else { print Not a Shipment Number, $REFln[1] type line.\n; } } Based on the input: CUR**USD REF*SN*0108106 REF*PO*cn190108106 REF*BL*cn190108106 REF*PS*JessupPA I expected to see SN: 0108106 (which I did) but I didn't expect to see SN: cn190108106 and SN: cn190108106, SN: JessupPA. I expected to see Not a Shipment Number, PO/BL/PS type line. for those. It almost seems like $REFln[1] is not being refreshed each time parseREF happens. I have written this same program in VB but I'm trying to do my parsing in Perl now . To tell you the truth I really don't have a clue why this doesn't work, so any help is much appreciated. Joel