in reply to Matching on a specific line of text

Yes it's possible. The special variable $. can be of great help, it keeps track of the line number of the filehandle you last read from. So you can do:
open IN, "<", $file or die "Can't open file $file: $!"; my %data; while(<IN>) { if($. == 1 || $. == 2) { my($number) = /([\d.]+)\s*$/; $data{$.} = $number; } }
If it doesn't match, it fills in undef for the data.

It's a bit silly for such small line numbers, but for larger numbers this approach begins to make sense.

I use a hash as a sparse array, it keeps a connection between the line number and the read data without wasting space for inbetween line numbers. Again, this makes most sense if your line numbers are much bigger than 1 or 2.

(update fixed error in code, thanks to davidrw for pointing that out.)

Replies are listed 'Best First'.
Re^2: Matching on a specific line of text
by bart (Canon) on May 07, 2006 at 19:29 UTC
    I forgot about the special behaviour of .. in scalar context, when the operands are literal integers. In that case, that value is automatically compared against $.. So my code can be simplified to:
    open IN, "<", $file or die "Can't open file $file: $!"; my %data; while(<IN>) { if(1 .. 2) { my($number) = /([\d.]+)\s*$/; $data{$.} = $number; } }

    If you need several distinct ranges, you can do

    if(1 .. 2 or 6 .. 8) {
    as can be demonstrated using the following code:
    while(<DATA>) { if(1 .. 2 or 6 .. 8) { print "$.: $_"; } } __DATA__ one two three four five six seven eight nine ten
    Result:
    1: one
    2: two
    6: six
    7: seven
    8: eight
    
    For a single value, you can choose between 4 == $. and 4 .. 4:
    if(1 .. 2 or 4 == $. or 6 .. 8) {
    if(1 .. 2 or 4 .. 4 or 6 .. 8) {
Re^2: Matching on a specific line of text
by davidrw (Prior) on May 07, 2006 at 18:54 UTC
    can add a else{ last } to the if statement so it doesn't bother reading the rest of the file.. Also, if the desired lines are at the beginning, can just do:
    my %data; ($data{$_}) = <IN> =~ m/(\d+\.\d+)\s*$/ for 1 .. 2;
    (note it's <IN>, not <$file>)
      add a else{ last } to the if statement so it doesn't bother reading the rest of the file.
      Careful if there are holes in your test range... you might jump out of the loop too early. In that case, it's best to do an explicit compare against the maximum line number you're interested in.
      elsif($. > $lastline) { last; }