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

I have a file that is large, (500+ lines). It used to be ok to append my few strings of text by using the command open(FILE, ">>/dir/file"); But now I need to add a few strings of text 30 lines prior to the "end of file";

ex:
line 1
line 2
....
line 569
line 570
....
line 600 (EOF)

I have 2 new lines which need to be added between lines 569 & 570.

Could anyone help me out? Thanks,
  • Comment on How do I add a few stings of text, 30 lines before the EOF?

Replies are listed 'Best First'.
Re: How do I add a few stings of text, 30 lines before the EOF?
by blakem (Monsignor) on Oct 16, 2001 at 03:29 UTC
Re: How do I add a few stings of text, 30 lines before the EOF?
by hopes (Friar) on Oct 16, 2001 at 03:26 UTC
    Why don't you want to read it all and then insert the lines?
    splice can be used to do the interpolation.
    use strict; open FILE, "fichero.txt"; my @lines = <FILE>; close FILE; my @newlines = ("First\n", "Second\n"); splice @lines,-30,0,@newlines; print @lines;

    Hopes
      Because I am looking for a more efficient method of doing this.
Re: How do I add a few stings of text, 30 lines before the EOF?
by michellem (Friar) on Oct 16, 2001 at 03:35 UTC
    Do you always know the length of the file, and know which line you want to put it in? If so:

    #!/usr/bin/perl -wT use strict; #get inserted text my @inserted_text = ('Blah','Blah Blah'); # read in the file open (FILE,"filename") or die "Can't open file"; my @file = <FILE> close(FILE) open (OUTFILE,">filename") or die "Can't open file"; my $line = 0; foreach(@file) { if ($line = 569) { foreach(@inserted_text){print OUTFILE;} } $line++; } close(OUTFILE);
    Otherwise, you could find out the length of the file, and then subtract 30 from the end of the length, and insert it there.

    This is untested code and, I'd bet 70 monks here could give you much, much better answers. I look forward to seeing them.

      Here's some updated information about my problem:

      The file I need to modify currently has 1107 lines. I need to insert 2 lines, 30 lines before the EOF --making the new line total 1109. So the file would continually get larger (1111, 1113, ...). I found that the 30 lines I'm trying to insert before, are exactly 947 bytes in length.

      Hopefully this information will help,
        Knowing exactly what byte location you want to insert at, you can seek to that location, read in the final bytes of the file, go back to that location and write out the new lines and the final bytes. To give some code:

        use Fcntl qw(:seek :flock); # get constants # location suitable for direct use in seek. use constant INSERT_LOCATION => (-947, SEEK_END); my $file = "..."; # open the file for update open FILE, "+<$file" or die "couldn't open $file: $!\n"; # don't have two copies of us update the file at the # same time... flock FILE, LOCK_EX or die "flock: $!\n"; # go to our location seek FILE, INSERT_LOCATION or die "seek: $!\n"; # read the rest of the file from there my $end = do { local $/; <FILE> }; defined $end or die "read: $!\n"; # go back to our location seek FILE, INSERT_LOCATION or die "seek: $!\n"; # write new data followed by old data from that point. print FILE $newlines, $end or die "print: $!\n"; close FILE or warn "close: $!\n";

        (I'm being incredibly paranoid by checking the return value of print and readline and close. You probably don't have to be.)

        Be forewarned that if the byte location is or becomes wrong then file curruption is likely.

Re: How do I add a few stings of text, 30 lines before the EOF?
by Anarion (Hermit) on Oct 16, 2001 at 12:32 UTC
    You have to count all the lines of the file, you can use $. for that, heres an example withoout reading all file in an array:

    #!/usr/bin/perl -w use strict; open(FILE,"file.txt") or die "Cant open file.txt: $!"; 1 while <FILE>; my $line=$.-30; $.=0; open(FILE,"file.txt") or die "Cant open file.txt: $!"; open(FILE2,">file2.txt") or die "Cant create file2.txt: $!"; while(<FILE>) { print FILE2 $_; insert(*FILE2) if $.==$line; } rename("file2.txt","file.txt") or die "Cant rename file: $!"; sub insert { my $fh=shift; print "Inserting at line $line\n"; print $fh "$_\n" for 0 .. 15; }


    $anarion=\$anarion;

    s==q^QBY_^=,$_^=$[x7,print