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

I want to count the number of the lines that contains keyword "energy" and the number of the lines that occur between the keyword "energy". The input file is as follows

536 ENERGY = -176.2 gag
1 G 0 2 0 1
2 G 1 3 533 2
3 G 2 4 532 3
536 ENERGY = -175.9 gag
1 G 0 2 0 1
2 G 1 3 533 2
3 G 2 4 532 3
As in this case the code should print 2 and 3 respectively. My code is just printing the number of lines containing "energy" which is 2 in this case. but not printing the number of lines within "energy" which is 3. My code is as follows:
open(MYFILE, $data_file) || die("Could not open file!"); @raw_data=<MYFILE>; foreach $c (@raw_data) { @c = $c; (@c[0],@c[1],@c[2], @c[3], @c[4], @c[5], @c[6])=split(/\s+/,$c); if(@c[2] eq ENERGY) { #print "energy found. reading next line\n"; while(@c[2] ne ENERGY) { $_=<MYFILE>; print $_; $count = $count + 1; } } } print "$count\n"; close(MYFILE);
Can anyone please help me?I guess there is something wrong with while loop. Your help will really be appreciated.

Replies are listed 'Best First'.
Re: How to read lines between specific character
by ikegami (Patriarch) on Nov 12, 2010 at 06:03 UTC

    Assuming you mean between the first ENERGY and the last ENERGY,

    while (<>) { if (/\bENERGY\b/) { ++$energy; if ($energy == 1) { $start = $.+1; } else { $end = $.; } } } say $energy; say $energy >= 2 ? $end-$start : 0;

      @ikegami....thankx

Re: How to read lines between specific character
by fisher (Priest) on Nov 12, 2010 at 07:38 UTC
    if by "between" you mean last occurence between:
    #!/usr/bin/env perl open F, "</tmp/fff"; $b=$between=$energy=0; while (<F>) { if (/energy/i) { $energy++; $between=$b; } elsif ($energy) {$b++} } print $energy, "/", $between;

      if you need to track the number of lines between MULTIPLE 'energy lines' then a modification to the above like this might be in the right direction ...

      #!/usr/local/perl5/bin/perl open F, "<./fff"; $b=$energy=0; @between = (); while (<F>) { if (/energy/i) { $between[$energy]=$b; $energy++; $b = 0; } else {$b++} } $between[$energy]=$b; my $i; printf("Before Energy 1 : %3d lines occur\n",$energy,$betwee +n[0]) if ($between[0] > 0); for($i = 1; $i < $energy; $i++) { printf("Between Energy %3d and %3d: %3d lines occur\n",$i,$i+1,$betwe +en[$i]); } printf("After Energy %3d : %3d lines occur\n",$energy,$betwee +n[$energy]);
      Misha/Michael - Russian student, grognard, bemused observer of humanity and self professed programmer with delusions of relevance

        thankx...i might need this logic in the next part of my code :) thankx

      thank you soo much.....it actually worked...thankalot

      thankx alot...it actually worked..... :)

      @fisher...thankx 4 help

      @fisher...thankx for help....it actually worked....thankxalot :)

Re: How to read lines between specific character
by graff (Chancellor) on Nov 13, 2010 at 02:17 UTC
    If I understand the goal, you just need a one-liner:
    perl -lne '$k=(/ENERGY/)?"e":"o";$c{$k}++;END{print "$c{e} $c{o}"}' da +ta.file
    As for why your script only printed the number of ENERGY lines, you read the entire content of the file into the "@raw_data" array, and used that array to count those lines (in a rather strange, non-optimal way), but you didn't use the same array to count the other lines.

    Instead, you went into a strange loop that tries to continue reading from the file (even though the entire file has already been read, so no more input is available). But you really don't need two passes over the data in any case; in a single pass, you can count the lines that contain ENERGY and the ones that don't.

      @graff...thankx for pointing out my mistake as well. Actually m new to programming + perl...thankx for explanation :)