Question

I need to cut a set of lines from a file between two mark points. For example the file is

file.txt

END  
line 1 not removed  
END  
line 2 not removed  
line 3 not removed  
BEGIN  
line 1 is to be removed  
line 2 is to be removed  
line 3 is to be removed  
END  
line two last not removed  
END  
line three last not removed  
line four last not removed  

I want to remove the lines between BEGIN and END. The new file becomes

file2.txt

END  
line 1 not removed  
END  
line 2 not removed  
line 3 not removed  
line two last not removed  
END  
line three last not removed  
line four last not removed  

This means BEGIN and the first END after BEGIN and the lines between them should be removed.

I was able to write this program, and it works perfectly. But is there any better way to do this?

use File::Copy;

$j = $i = 0;

open(DATA,  "<file1.txt");
open(DATA1, ">file2.txt");

while (<DATA>) {
  if ($_ =~ /^BEGIN/) { $i = 1; }
  if ($_ =~ /^END/ && $i == 1) { $i = 0; next if $_ }
  if ($i == 1) { next if $_; }
  print DATA1 $_;
}

close(DATA);
close(DATA1);

copy "file2.txt", "file1.txt";
Was it helpful?

Solution

while(<DATA>) {

  print DATA1 $_ unless /^BEGIN/ .. /^END/;
}

About the range .. operator from perldoc,

In scalar context, ".." returns a boolean value. The operator is bistable, like a flip-flop, and emulates the line-range (comma) operator of sed, awk, and various editors. Each ".." operator maintains its own boolean state, even across calls to a subroutine that contains it. It is false as long as its left operand is false. Once the left operand is true, the range operator stays true until the right operand is true, AFTER which the range operator becomes false again.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top