Copy selected lines from one file and paste those lines into another file after the selected line
Here's my question: let's say I have a file
file1.txt
with content:
abc..
def..
ghi..
def..
and a second file file2.txt
with content:
xxx.. yyy.. zzz..
Now I want to copy the whole line starting with "def" in file1.txt
before file2.txt
and add after the line "yyy ..." infile2.txt
Expected Result:
xxx...
yyy...
def...
def...
zzz...
I am very new in perl, I tried writing simple code for this, but in the end the output is only appended to the end of the 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);
perl program output
xxx...
yyy...
zzz...
def...
def...
source to share
I would use a temporary file.
- Read and print all lines (up to temp) from FILE2 until you hit "yyy"
- Read and print all "def" lines (up to temp) from FILE1
- Read and print (temporarily) the rest of FILE2
- 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";
source to share
The easiest way to do this is with a Tie::File
module, which allows you to access the file as a simple array of strings.
I also used first_index
from List::MoreUtils
to find where to insert 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 records from file1.txt
are inserted file2.txt
in the order they appear.
source to share