in reply to when reading a file how to print a line one above the current line??

First, if you want to open a file in that manner, you need to should get the file name from @ARGV instead of STDIN:
my $file = shift @ARGV;
No need to chomp it either. Next, if you want to print the line above the current line, you will need to print the line previously read. You could do this by slurping the file into an array, or you could just store the previous line in another scalar:
my $last; while (<MYFILE>) { if(/ALARM:/) { print $. - 1, ": $last"; print "$.: $_"; } $last = $_; }
Notice subtracting one from $. to get the previous line number as well. Everything else looks acceptable, well everything except that typo in your while expression.

jeffa

Quiz on Friday ;)

Replies are listed 'Best First'.
Re: (jeffa) Re: when reading a file how to print a line one above the current line??
by graff (Chancellor) on Jun 04, 2002 at 08:04 UTC
    Actually, there are situations where one would like to read file names from STDIN -- e.g.:
    ls *.log | show-the-alarms
    in which case, it'll be handy to have the file name(s) included in the output (I haven't tested this):
    while ( $file = <>) { chomp $file; my $status = "open file"; open( MYFILE, $file ) or next; $status = 0; my $last = ""; while (<MYFILE>) { if(/ALARM:/) { print "$file:", $. - 1, ": $last"; print "$file:$.: $_"; $status++; } $last = $_; } close MYFILE; } continue { print "Done with $file : found $status error(s)\n"; }
    That might not be what the questioner had in mind, but it's a reasonable approach.
      You still shouldn't read the filenames from STDIN. What you mention can and should be done by the shell: show-the-alarms `ls *.log`. Adding this ill-advised "functionality" to the script will only make it unnecessarily difficult to parse data not coming from a file.

      Makeshifts last the longest.

Re^2: when reading a file how to print a line one above the current line??
by Aristotle (Chancellor) on Jun 04, 2002 at 11:55 UTC

    But why tell him to read a filename at all in the case? I find that if one is taking filenames on the commandline, it's much better to use the diamond operator and let perl decide whether I should be reading from a bunch of files or STDIN, which allows for more flexibility.

    And some technical critique - you didn't guard your print $last. This is what I have in mind:
    #!/usr/bin/perl use strict; use warnings; my $prevline; while (<>) { if(/ALARM:/) { print $. - 1, ": $prevline" if defined $prevline; print "$.: $_"; } $prevline = $_; }
    ____________
    Makeshifts last the longest.
      Good point, but, personally, I'd do it as
      my $prevline = ''; ... print $. - 1, ": $prevline";
      This way doesn't have the overhead of testing every time whether $prevline is defined. Or you could initialize it to "BOF\n" for a more explicit indication of what's going on.
        I thought about the efficiency issue, but I guess it boils down to personal choice. With the guarded print you don't get to see a -1:\n should the pattern happen to match on the first line, and really that single test does very little to performance. We could pull out Benchmark here but I suspect the difference would be within measurement jitter (how is this exactly called in English?) for any less than a few hundred thousand lines.

        Makeshifts last the longest.