1

I have a text file where is lot of lines, I need search in this file keywords and if exist write to log file line where is keywords and line one line below and one above the keyword. Now search or write keyword not function if find write all and I dont known how can I write line below and above. Thanks for some advice.

my $vstup = "C:/Users/Omega/Documents/Kontroly/testkontroly/kontroly20220513_154743.txt";
my $log = "C:/Users/Omega/Documents/Kontroly/testkontroly/kontroly.log";
    
open( my $default_fh, "<", $vstup ) or die $!;
open( my $main_fh,    ">", $log )    or die $!;

my $var = 0;
while ( <$default_fh> ) { 
    if (/\Volat\b/)
        $var = 1;
    }
    if ( $var )
        print $main_fh $_;
    }
}

close $default_fh;
close $main_fh;
TLP
  • 66,756
  • 10
  • 92
  • 149
Filip Caha
  • 13
  • 2
  • I assume that the missing opening bracket in the if-clauses `{` is a typo....? – TLP May 17 '22 at 10:40
  • If the files are not too large, you can just slurp the file into an array. Then as long as you keep track of the index, printing the line before and after is easy `print @lines[$i-1, $i, $i+1]`. There are also modules like `Tie::File`. Or you can just keep track of the previous line, and when you match, print prev, current and next line. Or if on *nix, use `grep -w -A1 -B1 olat`. – TLP May 17 '22 at 10:44
  • yes, sorry I remove it when i edit a post. {. I tried to use print @lines[$i-1, $i, $i+1] but I don't know exactly how to write it. I declared: my $i; and replace print: print ( my @lines[$i-1, $i, $i+1], $main_fh )$_; – Filip Caha May 17 '22 at 12:23
  • Does this answer your question? [How can I print a matching line, one line immediately above it and one line immediately below?](https://stackoverflow.com/questions/1523846/how-can-i-print-a-matching-line-one-line-immediately-above-it-and-one-line-imme) – FractalLotus May 17 '22 at 19:24

1 Answers1

1

The approach below use one semaphore variable and a buffer variable to enable the desired behavior.

Notice that the pattern used was replaced by 'A` for simplicity testing.

#!/usr/bin/perl

use strict;
use warnings;


my ($in_fh, $out_fh);
my ($in, $out);
$in = 'input.txt';
$out = 'output.txt';

open($in_fh, "< ", $in) || die $!."\n";
open($out_fh, "> ", $out) || die $!;

my $p_next = 0;
my $p_line;
while (my $line = <$in_fh>) {
  # print line after occurrence
  print $out_fh $line if ($p_next);

  if ($line =~ /A/) {
    if (defined($p_line)) {
      # print previous line
      print $out_fh $p_line;

      # once printed undefine variable to avoid printing it again in the next loop
      undef($p_line);
    }
    
    # Print current line if not already printed as the line follows a pattern
    print $out_fh $line if (!$p_next);
    
    # toggle semaphore to print the next line
    $p_next = 1;

  } else {
    # pattern not found.
    
    # if pattern was not detected in both current and previous line.
    $p_line = $line if (!$p_next);
    $p_next = 0;
  }
}
close($in_fh);
close($out_fh);
PandaCheLion
  • 446
  • 5
  • 15