PERL: extract lines between two patterns

Hello Perl-experts,

I am new to perl and need help to solve a problem.

I have a table in below format.
<Text A>
<Pattern1>
A Value
B Value
C Value
D Value
<Pattern2>
<Text B>

This table is in file1. I want to extract lines between Pattern1 and Pattern2 and write it into file2. Please provide me some help to do this. Thanks

can you please write the real environment example

Thanks for your reply.

please find the actual code below.

#!/usr/bin/perl
use strict;
use warnings;

our $fh;
our $log;

open($fh,">","block.power");
open ($log,">","temp.log") or die "can not open file $log : $!\n" ;
while($fh){
   if (/Total Design Power Summary \(Worst/ ... /\|Total/)
  {printf $log;}
}

I'm getting below message when i run this script.

Use of uninitialized value in pattern match (m//) at temp.pl line 11.

if (/Total Design Power Summary \(Worst/ ... /\|Total/)
whats this

See if this helps...

perl -ne ' if(/<Pattern2>/){$p=0} if(/<Pattern1>/){$p=1;next}print if$p' infile > outfile

--ahamed

#!/usr/bin/perl -w
use strict;
use warnings;

print "enter the first pattern-:\n";
my $pat1=<>;
print "enter the second pattern-:\n";
my $pat2=<>;
my $en1=0;
my $en2=0;
open FILE, "<file1.txt" or die $!;
#my @lines=<FILE>;
my $i =0;
while(<FILE>)
{
	$i++;
if( $_ eq $pat1)
{	$en1=$i;
}
if( $_ eq $pat2)
{	 $en2=$i;
}
}
close(FILE);

open FILE, "<file1.txt" or die $!;
my @lines=<FILE>;

for(my $j=$en1; $j<($en2-1); $j++)
{
	print $lines[$j];
}
close(FILE);

check this if it helps you and please manipulate as per your requirment

---------- Post updated at 12:45 PM ---------- Previous update was at 12:45 PM ----------

#!/usr/bin/perl -w
use strict;
use warnings;

print "enter the first pattern-:\n";
my $pat1=<>;
print "enter the second pattern-:\n";
my $pat2=<>;
my $en1=0;
my $en2=0;
open FILE, "<file1.txt" or die $!;
#my @lines=<FILE>;
my $i =0;
while(<FILE>)
{
	$i++;
if( $_ eq $pat1)
{	$en1=$i;
}
if( $_ eq $pat2)
{	 $en2=$i;
}
}
close(FILE);

open FILE, "<file1.txt" or die $!;
my @lines=<FILE>;

for(my $j=$en1; $j<($en2-1); $j++)
{
	print $lines[$j];
}
close(FILE);

chech this if it helps you and please manipulate as per your requirment

With possible corrections.

#!/usr/bin/perl
use strict;
use warnings;

our $fh;
our $log;

open($fh,"<","block.power"); # Here the arrow should point towards left to imply you're reading from file.
open ($log,">>","temp.log") or die "can not open file $log : $!\n" ; # Use >> to append. You don't want the log file to contain only the last printed line, do you?
while($fh){
   if (/Total Design Power Summary \(Worst/../\|Total/)
  {printf $log;}
}
close $log; #Though your file handles would close upon exit, 
close $fh; # its always a good practice to close them yourself.

hi balajesuri..
Nice Script....
Can you please explain me the lineif (/Total Design Power Summary \(Worst/../\|Total/).

I didn't get it clearly. Thanks in advance.
I learn from you very much.

if-condition is true if current line in buffer is in between the two patterns

thats true. but i want to know how does it execute
/Total Design Power Summary \(Worst/../\|Total/

Thanks to all of you for your help. Now I'm able to get my code work.
Posting it below.

#!/usr/bin/perl 
#use strict; 
#use warnings; 
my $fh; 
my $log; 
my $line;
open($fh,"<","file1") or die "can not open file $fh : $!\n" ; 
open ($log,">","file2")or die "can not open file $log : $!\n" ; 
while($line = <$fh>)
{
   if ($line =~ /pattern1/ ) 
   {  
	  printf $log $line;
	  while($line = <$fh>) 
	  {
		 if($line =~ /pattern2/)
		 {
			printf $log $line;  
			last;
		 } else
		 {
			printf $log $line;  
		 }  
     }
     }
   } 
close $fh;
close $log;

Happy to take your advice to make this code more efficient.

@mnithink: Not sure how your code worked! It doesn't work for me. Try this: (and please use code tags)

#!/usr/bin/perl
use strict; # Its a good practice not to comment these two pragmas.
use warnings;

open I, "< file1";
open O, "> file2";

foreach (<I>) {
    if (/Pattern1/ .. /Pattern2/) { print O }
}

close O;
close I;

@parthmittal2007: (/Pattern1/../Pattern2/) is known as flip-flop operator in perl. Imagine this: While reading a file line by line, perl sets an internal flag to true the moment it encounters 'Pattern1' and the if-block is executed until it encounters 'Pattern2' in a line (when it sees Pattern2, it sets the same internal flag to false). Thus, for lines before Pattern1 or after Pattern2 the flag would be false, thereby failing the if-condition.

For e.g.:

foreach (<I>) {
    if (/Pattern1/ .. /Pattern2/) { print O }
}

This would print all the lines in between (and inclusive of) 'Pattern1' and 'Pattern2' into the out file-handle.

1 Like