Emman
Emman

Reputation: 1234

Copy selected lines from one file and insert those lines in another file after selected line

Here is my question let's say I have a file file1.txt with contents:

abc.. 
def.. 
ghi.. 
def..

and second file file2.txt with contents:

xxx..
yyy..
zzz..

Now I want to copy all the line starting with "def" in file1.txt to file2.txt and append after "yyy..." line in file2.txt

Expected Output:

xxx...
yyy...
def...
def...
zzz...

I am pretty much new to perl, I've tried writing simple code for this but end up with output only appending at the end of file

#!/usr/local/bin/perl -w 
use strict; 
use warnings;
use vars qw($filecontent $total);
my $file1 = "file1.txt";
open(FILE1, $file1) || die "couldn't open the file!";
open(FILE2, '>>file2.txt') || die "couldn't open the file!";
  while($filecontent = <FILE1>){
    if ( $filecontent =~ /def/ ) {
      chomp($filecontent);
       print FILE2 $filecontent ."\n";
      #print FILE2 $filecontent ."\n" if $filecontent =~/yyy/;
    }  
  } 
 close (FILE1); 
 close (FILE2);

output of the perl program is

xxx...
yyy...
zzz...
def...
def...

Upvotes: 3

Views: 8722

Answers (3)

ingydotnet
ingydotnet

Reputation: 2613

You might want to try the IO::All module:

use IO::All;
my ($f1, $f2, $i) = (io('file1.txt'), io('file2.txt'), 1);
for (@$f2) {
    splice(@$f2, $i, 0, grep /^def/, @$f1), last
        if /^yyy/;
    $i++;
}

Upvotes: 2

Borodin
Borodin

Reputation: 126722

The simplest way to do this is with the Tie::File module, that lets you access a file as a simple array of strings.

I have also used first_index from List::MoreUtils to find where to insert the records.

use strict;
use warnings;

use Tie::File;
use List::MoreUtils qw/ first_index /;

tie my @file1, 'Tie::File', 'file1.txt' or die $!;
tie my @file2, 'Tie::File', 'file2.txt' or die $!;

my $insert = first_index { /^yyy/ } @file2;

for (@file1) {
  if ( /^def/ ) {
    splice @file2, ++$insert, 0, $_;
  }
}

output (file2.txt)

xxx..
yyy..
def.. 
def..
zzz..

Your test data doesn't cover it, but the records from file1.txt are inserted into file2.txt in the order that they appear.

Upvotes: 2

Paul Roub
Paul Roub

Reputation: 36438

I'd use a temp file.

  1. Read and print all lines (to temp) from FILE2 until you hit "yyy"
  2. Read and print all "def" lines (to temp) from FILE1
  3. Read and print (to temp) the rest of FILE2
  4. Rename the temp file to FILE2
use strict; 
use warnings;

my $file1 = "file1.txt";
my $file2 = "file2.txt";
my $file3 = "file3.txt";

open(FILE1, '<', $file1) or die "couldn't open the file!";
open(FILE2, '<', $file2) or die "couldn't open the file!";
open(FILE3, '>', $file3) or die "couldn't open temp file";

while (<FILE2>) {
  print FILE3;
  if (/^yyy/) {
    last;
  }
}

while (<FILE1>) {
  if (/^def/) {
    print FILE3;
  }
}

while (<FILE2>) {
  print FILE3;
}

close (FILE1); 
close (FILE2);
close (FILE3);

rename($file3, $file2) or die "unable to rename temp file";

Upvotes: 5

Related Questions