Reputation: 1990
I have a file like some.txt
having content :
#start-first
Line 1
Line 2
Line 3
#end-first
#start-second
Line 1
Line 2
Line 3
Line 4
#end-second
#start-n
Line 1
Line 2
Line 3
Line 4
...
...
#end-n
I want to delete content from file from #start-second
to #end-second
or from #start-n
to #end-n
, actually #start-second
is Start Marker for Second Text Block of file and #end-second
is End Marker for Second Text Block of file.
How to delete content from Specific Start Block to same End block ?
Upvotes: 0
Views: 133
Reputation: 21661
Here is my solution:
It's a bit more difficult to do it line by line, but it does let you manage memory better for large files, because your not opening the entire file all at once. Also you can replace multiple blocks a bit easier this way.
$file = 'test.txt';
//open file to read from
$f = fopen(__DIR__.DIRECTORY_SEPARATOR.$file,'r');
//open file to write to
$w = fopen(__DIR__.DIRECTORY_SEPARATOR.'out-'.$file,'w');
$state = 'start'; //start, middle, end
//start - write while looking for a start tag ( set to middle )
//middle - skip while looking for end tag ( set to end )
//end - skip while empty ( set to start when not )
//Tags
$start = ['#start-second'];
$end = ['#end-second'];
//read each line from the file
while( $line = fgets($f)){
if( $state == 'end' && !empty(trim($line))){
//set to start on first non empty line after tag
$state = 'start';
}
if( $state == 'start' ){
if(in_array(trim($line),$start)){
$state = 'middle';
}else{
fwrite($w, $line);
}
}else if( $state == 'middle' ){
if(in_array(trim($line),$end)){
$state = 'end';
}
}
}
//close both files
fclose($f);
fclose($w);
//delete the input file
//unlink(__DIR__.DIRECTORY_SEPARATOR.$file);
//for debugging only
echo "<pre>";
echo file_get_contents(__DIR__.DIRECTORY_SEPARATOR.'out-'.$file)
And the output
#start-first
Line 1
Line 2
Line 3
#end-first
#start-n
Line 1
Line 2
Line 3
Line 4
...
...
#end-n
This will also accept an array of tags, so you can remove multiple chunks per go.
Most the PHP sandboxes ( or code sandboxes in general ) prevent you from using the functions, for security reasons. That said, we can emulate
the body of the code, the parsing bit, to some extent. So that is what I have done here.
http://sandbox.onlinephpfunctions.com/code/0a746fb79041d30fcbddd5bcb00237fcdd8eea2f
That way you can try a few different tags and see how it works. For extra credit you could make this into a function that accepts the filepath and an array of open and start tags.
/**
* @var string $pathName - full path to input file
* @var string $outputName - name of output file
* @var array $tags - array of tags ex. ['start'=>['tag1'],'end'=>[...]]
* @return string - path to output file
*/
function($pathName, $outputName, array $tags){
....
}
Upvotes: 0
Reputation: 16103
If these files are really big, there is a fairly lightweight solution:
$file = file_get_contents("example.txt");
// Find the start "#start-$block", "#end-$block" and the length between them:
$start = strpos($file, "#start-$block");
$end = strpos($file, "#end-$block");
$length = $end-$start+strlen("#end-$block");
$file = substr_replace($file, '', $start, length);
file_put_contents("example.txt", $file);
My original answer started with a regex:
$block = 4;
// Open the file
$file = openfile("example.txt");
// replace #start-$block, #end-$block, and everything inbetween with ''
$file = preg_replace("/#start\-".$block."(?:.*?)#end\-".$block."/s", '', $file);
// Save the changes
file_put_contents("example.txt", $file);
Regexes are expensive though, but sometimes easier to understand.
Upvotes: 2