PyrexKidd has asked for the wisdom of the Perl Monks concerning the following question:

I need to write a script that inserts text from fileA at a specific point in the middle of fileB. the location is determined by $searchParameter.

Really what i'm doing is similar to ^R in nano.

normally what i would do is read the fileB into an array, insert the text in the middle of the array and write the array back to the fileB. the problem i'm having is the file is too large to be stored in memory.

any suggestions on how to insert fileA into fileB

Replies are listed 'Best First'.
Re: append middle of File
by Anonymous Monk on Apr 10, 2010 at 08:34 UTC
    There is no reason to read file into memory
    $ cat 2 1 2 3 4 $ perl -i.orig -p -l -e "print 'three' if /3/" 2 $ cat 2 1 2 three 3 4 $ cat 2.orig 1 2 3 4 $ perl -MO=Deparse -i.orig -p -l -e "print 'three' if /3/" BEGIN { $^I = ".orig"; } BEGIN { $/ = "\n"; $\ = "\n"; } LINE: while (defined($_ = <ARGV>)) { chomp $_; print 'three' if /3/; } continue { print $_; } -e syntax OK
      So here is what I have. This just appends the end of the file which is close but not what I need. I need to add fileA in the MIDDLE of FileB
      #!/usr/bun/perl #------------------------------ # This script searches for "search" # and adds lines from fileSource to fileOutput use warnings; use strict; #use Fcntl (:flock :seek); # Check unless(-e $ARGV[0] || -e $ARGV[1]){ print("Please Enter A Valid File Name\n"); exit 1; } #if($ARGV[0] == "--help"){ # print("Usage is:\n"); # print("perl conference_add.pl <Source File> <Output File> <Sear +ch String>"); #} # assigns file path to local variables my($fileSource) = $ARGV[0]; my($fileOutput) = $ARGV[1]; my(@inputLines); # opens files for reading/writing open(FILESOURCE, "<", $fileSource) || die("Can not open $fileSource $! +"); open(FILEOUT, ">>", $fileOutput) || die ("Can not open $fileOutput $!" +); @inputLines = <FILESOURCE>; print FILEOUT @inputLines; close(FILESOURCE); close(FILEOUT);
        I'd do it like this:
        #!/usr/bin/perl use strict; use warnings; ( @ARGV == 3 and -f $ARGV[0] ) or die "Usage: $0 primary.file secondary.file insertion_point_ +pattern\n"; open( my $in1, "<", $ARGV[0] ) or die "$ARGV[0]: $!\n"; open( my $in2, "<", $ARGV[1] ) or die "$ARGV[1]: $!\n"; open( my $out, ">", "$ARGV[1].including.$ARGV[0]" ) or die "$ARGV[1].including.$ARGV[0]: $!\n"; while ( <$in2> ) { print $out $_; # assuming you want content added after target p +attern if ( /$ARGV[2]/ and $in1 ) { while ( <$in1> ) { print $out $_; } close $in1; $in1 = undef; } }
        You might want to include a couple of "rename" steps after the outer while loop (rename the old "secondary.file" to "secondary.file.old", rename the output file to "secondary.file").

        Note that if the given pattern never matches anything in the secondary file, the primary file never gets read or added to the output (output will be identical to input).

Re: append middle of File
by CountZero (Bishop) on Apr 11, 2010 at 07:49 UTC
    Perhaps it is more clear if we give you an algorithm rather than a script:
    1. Open your output file (say fileC)
    2. Open your fileB
    3. Read through fileB file line by line, finishing if all lines have been read.
    4. Have you reached the place of insertion? If no, print to your output file, the line just read and go back to 3. If yes, open fileA and print all of it to your output file.
    A rather minimal version of this algorithm could be:
    use strict; use warnings; open my $FILEC, '>', 'fileC'; open my $FILEB, '<', 'fileB'; open my $FILEA, '<', 'fileA'; while (my $line = <$FILEB>) { do {local $_; print $FILEC $_ while (<$FILEA>)} if $line =~ m/INSE +RT BEFORE HERE/; print $FILEC $line; }
    By using a while loop both on the original file and the file to be inserted you never have more than a few lines in memory, so it will work on any size of file.

    Of course you should add some tests to see whether opening of the files and writing to them succeeds.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James