in reply to Reading in N lines at a time

tachyon has answered your specific question. But here are come general suggestions that you may find helpful. Mostly pertaining to the regex and the code lines following it.

The var name '$lines' is confusing. (I find myself asking what you are trying to tell me -- is it really more than one line each time?) I'd just call it '$line'.

Your regex does not line up with the sample data you have shown (no leading field of digits in the sample) but you'll sort that out on your own.

In the regex, you don't need to escape ':' and if you use a different regex delimiter, you don't need to escape '/'.

Also, you don't need to put parentheses around (\s+) since you are not capturing these for use later. And omitting those makes the fields you do want to capture a little spiffier to recover as explained below.

When capturing several values into a hash at once, a hash slice is a slick way to condense code. The verbose way to do this here would be:

my %vars; @vars{'d','map','proto','uri1','uri2'} = ($1,$3,$5,$6,$8);
But since we dropped the unneeded parens around the spaces, the desired fields are now just $1,$2,$3,$4,$5. That makes it easy to grab them directly by pre-loading them into another array.

So this:

if ($lines=~/(\d+)(\s+)(map|reverse_map)(\s+)(\w+)\:\/\/(.*?)(\s+)(\5) +\:\/\/(.*?)$/) { $vars{'d'} = $1; $vars{'map'} = $3; $vars{'proto'} = $5; $vars{'uri1'} = $6; $vars{'uri2'} = $8; } } my $result = $template->fill_in(HASH => \%vars);
Becomes this. (Untested... but probably pretty close):
my @fields = qw(d map proto uri1 uri2); if (@vars{@fields} = $line=~m#(\d+)\s+(map|reverse_map)\s+(\w+)://(.*? +)\s+(\5)://(.*?)$#) { my $result = $template->fill_in(HASH => \%vars); }
I may have taken liberties with the logic of your curly-braces, but you get the idea.

HTH -- David

Replies are listed 'Best First'.
Re: Re: Reading in N lines at a time
by Tuna (Friar) on Aug 15, 2001 at 17:21 UTC
    Hey, thanks for making time to point this out to me. I find it very helpful. Yeah, the live data doesn't contain leading digits; I intentionally put them there, in order to make my test print statements a bit easier to read.
      You might consider using $. instead of the leading didget. It will give you the line number of the last line read without the need to alter the way your script parses it's input when you are done debuging.
Re: Re: Reading in N lines at a time
by Tuna (Friar) on Aug 15, 2001 at 18:55 UTC
    hmmm. Something is wrong that I can't figure out:

    #!/usr/bin/perl -w use strict; use Text::Template; my %vars; my $line; my @fields; my $result; my $file = "/home/trixee/20010814/remap.tmpl"; my $cfg = "/home/trixee/20010814/remap.config"; my $template = new Text::Template (SOURCE => $file) or die "Couldn't construct template: $Text::Template::ERROR"; open FH, "$cfg" or die "$!\n"; while ($line = <DATA>) { chomp $line; next if ($line =~ /^\#/); @fields = qw(map proto uri1 uri2); if ( @vars{@fields} = $line=~m!(map|reverse_map)\s+(\w+)://(.*?)\s ++\2://(.*?)$! ) { $result = $template->fill_in(HASH => \%vars); } if ($result) { print "$result\n"; } else { die "Couldn't fill in template: $Text::Template::ERROR" } } __DATA__ # Automatic mapping tables generated from Magma map http://www.digitalcity.com http://origin-www.digitalcity.com map tunnel://www.digitalcity.com tunnel://origin-www.digitalcity.com map http://10.0.2.1 http://origin-www.digitalcity.com map tunnel://10.0.2.1 tunnel://origin-www.digitalcity.com reverse_map http://origin-www.digitalcity.com http://www.digitalcity.c +om reverse_map tunnel://origin-www.digitalcity.com tunnel://www.digitalci +ty.com Template: {$map} {$proto}://{$uri1} {$proto}://{$uri2} {$map} {$proto}://{$uri1} {$proto}://{$uri2} {$map} {$proto}://{$uri1} {$proto}://{$uri2} {$map} {$proto}://{$uri1} {$proto}://{$uri2} {$map} {$proto}://{$uri2} {$proto}://{$uri1} {$map} {$proto}://{$uri2} {$proto}://{$uri1}

    prints

    map http://www.digitalcity.com http://origin-www.digitalcity.com map http://www.digitalcity.com http://origin-www.digitalcity.com map http://www.digitalcity.com http://origin-www.digitalcity.com map http://www.digitalcity.com http://origin-www.digitalcity.com map http://origin-www.digitalcity.com http://www.digitalcity.com map http://origin-www.digitalcity.com http://www.digitalcity.com map tunnel://www.digitalcity.com tunnel://origin-www.digitalcity.com map tunnel://www.digitalcity.com tunnel://origin-www.digitalcity.com map tunnel://www.digitalcity.com tunnel://origin-www.digitalcity.com map tunnel://www.digitalcity.com tunnel://origin-www.digitalcity.com map tunnel://origin-www.digitalcity.com tunnel://www.digitalcity.com map tunnel://origin-www.digitalcity.com tunnel://www.digitalcity.com map http://10.0.2.1 http://origin-www.digitalcity.com map http://10.0.2.1 http://origin-www.digitalcity.com map http://10.0.2.1 http://origin-www.digitalcity.com map http://10.0.2.1 http://origin-www.digitalcity.com map http://origin-www.digitalcity.com http://10.0.2.1 map http://origin-www.digitalcity.com http://10.0.2.1 map tunnel://10.0.2.1 tunnel://origin-www.digitalcity.com map tunnel://10.0.2.1 tunnel://origin-www.digitalcity.com map tunnel://10.0.2.1 tunnel://origin-www.digitalcity.com map tunnel://10.0.2.1 tunnel://origin-www.digitalcity.com map tunnel://origin-www.digitalcity.com tunnel://10.0.2.1 map tunnel://origin-www.digitalcity.com tunnel://10.0.2.1 reverse_map http://origin-www.digitalcity.com http://www.digitalcity.c +om reverse_map http://origin-www.digitalcity.com http://www.digitalcity.c +om reverse_map http://origin-www.digitalcity.com http://www.digitalcity.c +om reverse_map http://origin-www.digitalcity.com http://www.digitalcity.c +om reverse_map http://www.digitalcity.com http://origin-www.digitalcity.c +om reverse_map http://www.digitalcity.com http://origin-www.digitalcity.c +om reverse_map tunnel://origin-www.digitalcity.com tunnel://www.digitalci +ty.com reverse_map tunnel://origin-www.digitalcity.com tunnel://www.digitalci +ty.com reverse_map tunnel://origin-www.digitalcity.com tunnel://www.digitalci +ty.com reverse_map tunnel://origin-www.digitalcity.com tunnel://www.digitalci +ty.com reverse_map tunnel://www.digitalcity.com tunnel://origin-www.digitalci +ty.com reverse_map tunnel://www.digitalcity.com tunnel://origin-www.digitalci +ty.com

    Why?

      From your description you gave in the CB, you're looking for it to print 6 lines according to the layout of the template.

      It is doing that, bu not as I assume you wish. I'm not all that knowledgeable about Text::Template, but this is what I see happening. You're defining your fields..

      @fields = qw(map proto uri1 uri2);
      ..then you are parsing and passing your data..
      if ( @vars{@fields} = $line=~m!(map|reverse_map)\s+(\w+)://(.*?)\s ++\2://(.*?)$! ) { $result = $template->fill_in(HASH => \%vars); }
      ...and your template looks like this..
      {$map} {$proto}://{$uri1} {$proto}://{$uri2} {$map} {$proto}://{$uri1} {$proto}://{$uri2} {$map} {$proto}://{$uri1} {$proto}://{$uri2} {$map} {$proto}://{$uri1} {$proto}://{$uri2} {$map} {$proto}://{$uri2} {$proto}://{$uri1} {$map} {$proto}://{$uri2} {$proto}://{$uri1}
      Now, you read one(1) line, parsed it and passed it to fill in the template. For the first line, your values are going to look like this..
      $map => map $proto =>http $uri1 => www.digitalcity.com $uri2 => origin-www.digitalcity.com
      When you pass it to $template->fill_in(), it fills in the whole template. So on the line, the template is filled in completely (all six lines) and the results are the first 6 that are printed. Rinse, wash and repeat for the rest of the lines you're parsing.

      I assume that this isn't the effect that you want. But to fix it you're going to have to take a different approach. Namely, reading in 6 lines and using different variables on each line to designate which values go where.

      There might be a better way using Text::Template but I'm really not all that familiar with the module.

      Hope this helps..
      Rich