Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Help Matching Sections of a file

by smaida (Initiate)
on Apr 04, 2004 at 23:59 UTC ( #342534=perlquestion: print w/replies, xml ) Need Help??

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

Hi,
I am working on a perl script that needs to read in an entire text file and print out a certain section based on the input
Part of the text file is as follows--
Port 119 NNTP * Microsoft Ports-Microsoft Exchange supports a News server running at + this port. * RFC977 * RFC1036 #------------------------------------------- Port 120 CFDP (UDP) Coherent File Distribution Protocol (CFDP) * RFC1235 #------------------------------------------- Port 123 NTP (UDP) NTP (Network Time Protocol) * RFC2030 * RFC1129 #--------------------------------------------
I need the script to read in and search the text file for a line "Port $port" where $port is the port number and then print out everyline until the "#-----" line.

Currently I have the following which searches the text file and finds the line "Port $port"... But where do I go from there?

sub port_definition { my $port = @_[0]; open(FILE,"ipac_port_defs") || die_nice("Can not open file \"ipac_p +ort_defs\" for reading"); @port_file = <FILE>; close(FILE); foreach $line(@port_file){ if ($line =~ /^Port\s$port/){ $template{port_def} = $line; } } print "Content-type: text/html\n\n"; # Print headers parse("tpl/port_def"); }

If someone could just point me in the right direction.
Thanks,
Shawn

Replies are listed 'Best First'.
Re: Help Matching Sections of a file
by kvale (Monsignor) on Apr 05, 2004 at 00:10 UTC
    An alteration like this would do what you want:
    my $found_port; foreach my $line (@port_file) { if ($line =~ /^Port\s$port/) { $found_port = 1; $template{port_def} = $line; } next unless $found_port; last if $line =~ /^#----/; print $line; }

    -Mark

Re: Help Matching Sections of a file
by jmcnamara (Monsignor) on Apr 05, 2004 at 00:31 UTC

    Here is one way to do it. This example changes $/ to read the records one at a time. The regex may need to be extended a little and you could use an array instead of a hash.
    #!/use/bin/perl -w use strict; my %ports; $/ = "#-------------------------------------------\n"; while (<DATA>) { chomp; $ports{$1} = $_ if m/^\s+Port (\d+)/; } print $ports{120}; __DATA__ Port 119 NNTP * Microsoft Ports-Microsoft Exchange ... * RFC977 * RFC1036 #------------------------------------------- Port 120 CFDP (UDP) Coherent File Distribution Protocol (CFDP) * RFC1235 #------------------------------------------- Port 123 NTP (UDP) NTP (Network Time Protocol) * RFC2030 * RFC1129

    --
    John.

Re: Help Matching Sections of a file
by TilRMan (Friar) on Apr 05, 2004 at 02:21 UTC
    Gotta plug the .. operator (untested):
    my $port = "1234"; open FILE, blah blah blah or die; while (<FILE>) { print if /Port\s+$port/ .. /^#---/; } close FILE;
        Gotta plug the .. operator (untested):
      Nice one TilRMan! I was playing with it some more to get rid of the '#----' and I came up with:
      #!/usr/bin/perl my $port = $ARGV[0] or die "usage: $0 <portnumber>\n"; while (<DATA>) { print if /Port\s+$port/ .. /^#---/ and !/^#---/; } __DATA__ Port 119 NNTP * Microsoft Ports-Microsoft Exchange supports a News server running at + this port. * RFC977 * RFC1036 #------------------------------------------- Port 120 CFDP (UDP) Coherent File Distribution Protocol (CFDP) * RFC1235 #------------------------------------------- Port 123 NTP (UDP) NTP (Network Time Protocol) * RFC2030 * RFC1129 #--------------------------------------------
      Is there a way to do this with the '..' or '...' operator without having to do the extra match (the and !/^#---/ part)?
        How about (not well tested):
        while (<FOO>) { print if /Port\s+$port\b/ .. /^#---/ && last; }
        The last also fixes the (presumed) problem of looping through the whole file even after you've found the relevant section. Notice the \b too which I forgot.
Re: Help Matching Sections of a file
by BrowserUk (Patriarch) on Apr 05, 2004 at 01:19 UTC

    If your going to re-read the file every run, and assuming that the record separator is consistant (which it isn't in your sample data), then it might be more efficient to read the records, record by record by setting $/ to the separator, and only reading as many as needed.

    #! perl -slw use strict; sub port_definition{ my( $port, $def ) = shift; #open FILE, '<', .... local $/ = '#-------------------------------------------'; 1 until ($def = <DATA>) =~ m[Port $port]; return $def; } print port_definition 123 ; __DATA__ Port 119 NNTP * Microsoft Ports-Microsoft Exchange supports a News server running at + this port. * RFC977 * RFC1036 #------------------------------------------- Port 120 CFDP (UDP) Coherent File Distribution Protocol (CFDP) * RFC1235 #------------------------------------------- Port 123 NTP (UDP) NTP (Network Time Protocol) * RFC2030 * RFC1129 #-------------------------------------------

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
Re: Help Matching Sections of a file
by Elijah (Hermit) on Apr 05, 2004 at 01:14 UTC
    for (@port_file) { $match = 1 if (/^Port\s*$port/); undef $match if (/^#-+/); print if ($match); }
Re: Help Matching Sections of a file
by Happy-the-monk (Canon) on Apr 05, 2004 at 00:13 UTC

    to print $line

    print $line;

    you only want to print it if there was a match before, and if it isn't a #--------------------------------------------:

    if ( $line !~ m/^#\-{44}/ ) { undef $match } # kvale's solution with last
    # is probably better because it stops reading lines from the array.
    # Use this switch if you are going to print more than one section in the file.

    print $line if $match;

    You still have to switch on $match = 1 in the code you already have got.

    Cheers, Sören

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://342534]
Approved by Happy-the-monk
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (2)
As of 2023-12-10 07:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    What's your preferred 'use VERSION' for new CPAN modules in 2023?











    Results (38 votes). Check out past polls.

    Notices?