kirk123 has asked for the wisdom of the Perl Monks concerning the following question:

Hi I have the following data in a file:
device for another: /dev/another system for fdfdf: sleepy (as printer dsdsds) device for network: /dev/network device for llp: /dev/ecpp0 system default destination: another printer llp is idle. enabled since Wed Oct 23 15:54:08 GMT 2002. avail +able. Form mounted: Content types: any Printer types: unknown Description: OPENprint printer llp Connection: direct Interface: /usr/lib/lp/model/standard On fault: write to root once After fault: continue Users allowed: (all) Forms allowed: (none) Banner not required Character sets: (none) Default pitch: Default page size: Default port settings: -opost printer network is idle. enabled since Fri Feb 7 00:50:11 GMT 2003. a +vailable. Form mounted: Content types: simple Printer types: unknown Description: none Connection: direct Interface: /usr/lib/lp/model/net_lj4x On fault: write to root once After fault: continue Users allowed: (all) Forms allowed: (none) Banner required Character sets: (none) Default pitch: Default page size: Default port settings: printer another is idle. enabled since Fri Feb 7 01:49:02 GMT 2003. a +vailable. Form mounted: Content types: simple Printer types: unknown Description: sdsd Connection: direct Interface: /usr/lib/lp/model/net_lj4x On fault: write to root once After fault: continue Users allowed: (all) Forms allowed: (none) Banner required Character sets: (none) Default pitch: Default page size: Default port settings: printer fdfdf unknown state. enabled since Feb 07 16:56 2003. availabl +e. Description: dsdsds@sleepy Remote Name: dsdsds Remote Server: sleepy dsdsds: unknown printer
I need to read through the file and print it out as follow:
llp|Local|standard|OPENprint printer llp|Up|0|no| network|Network|net_lj4x|none|Up|0|no another|Network|net_lj4x|sdsd|Up|0|no fdfdf|Remote|sleepy|dsdsds@sleepy|Up|1|N/A
#Note Basically I am grabbing the first word after "printer" and putting it in an array.

If this word matches the last word in the line "device for" I add the word "Network" to the array. If it doesn't I add the word "local". If it matches the word after "system for" , I add "Remote" to the array.

Next I get the last word from the string that start with the word "Interface:" and put it in the array. example: "net_lj4x" and "standard"

Next I get the whole string after "Description:" and I put it in the array.

Next I add the word "Up" to the array.

Next I add the number zero to the array.

Last if the first word after "printer" matches the first word after "system for" I add the word " N/A" else I add the word "no"

I print out the array and then I read the next line from file and I start the process again.

Here my code .

use strict; my @words; my $banner; my @array; my $i = 0; my @strings; my @test; open RI,"<c:\\junk.txt" || die "Can't open test.txt for reading: $!\n" +; while(<RI>) { if (/^printer/) { # IF ARRAY IS NOT EMPTY if ( @array ) { for ( sort { $a->[1] <=> $b->[1] } @array ) { print "$_->[0]|"; } print "\n"; @array=(); $i =0; } @strings = (split)[1,3,4,5]; if ( $strings[1] eq "idle." ) { push @array, [ "0", 6 ]; } else { #QUEUE JOBS #my $number = `lpstat -o $strings[0] | wc -l | sed -e +'s/^ *//'`; #chomp($number); #push @array, [ $number, 6 ]; } # if ( $strings[2] eq "enabled" ) { my $s = "Up"; push + @array, #+[ $s, 5 ]; } # if ( $strings[3] eq "enabled" ) my $s = "Up"; push @array,+[ $s, 5 ]; push @array, [ $strings[0], 1 ]; #$strings[0] is the na +me of printer } # END OF /PRINTER/ elsif (m|Interface:(.+)|i) { @words = split(/\//, $_); chomp($words[-1]); push @array, [ $words[-1], 3]; } elsif (m|Description: (.+)|i) { push @array, [ $1, 4]; } elsif (m|Connection: (.+)|i) { if ($1 eq "direct" ) { push @array, [ "Local", 2]; } } elsif (/Banner not required/) { # push @array, ["No",7 ]; # $banner=`awk -F '/^BANNER/ { print $1 }' /etc/lp/interfaces/$ +strings[0] | sed 's/ *# CHANGE BANNER PAGE PRINTING//'`; chomp($banner); if( $banner eq "BANNER=\"\"") { push @array, ["No",7 ]; } elsif( $banner eq "BANNER=\"yes\"") { push @array, ["yes",7 ]; } else { push @array, ["no",7 ]; } } }#END OF WHILE LOOP for ( sort { $a->[1] <=> $b->[1] } @array ) { print "$_->[0]|"; } print "\n";
The script was written before the first six lines in the data was added. Now I had to modify it because of the first six lines.

As you can see in the output the word after "network" and "Another" should have been "Network" not "Local".

Appreciate it if someone could show me how to modify my code to get the desired result.

--kirk123 I

20030208 Edit by Corion : Added Readmore tags

Replies are listed 'Best First'.
Re: Complex texts parsing
by jdporter (Paladin) on Feb 07, 2003 at 22:25 UTC
    My code below parses the file as you describe.
    However, there is some logic you seem to be missing. In particular, you show a "1" in the next-to-last field for the Remote printer entry, but your description doesn't allow for that.
    Hopefully you'll be able to take this code and enhance it.
      Thanks jdporter, Hopefully one day I can help someone else in need.