in reply to New Line at End File

Well, if the file is not too large to fit in memory ---
{ local @ARGV = $file_name; local $^I = ''; # edit file in place (UPDATED) local $/; # sluurp local $_ = <>; while ( chomp ) { } print; }

jdporter
...porque es dificil estar guapo y blanco.

Replies are listed 'Best First'.
Re: New Line at End File
by Willman023 (Scribe) on Dec 10, 2002 at 04:03 UTC
    You could also use File::ReadBackwards to read in just the last line and test for the newline characters.

    use File::ReadBackwards; $bw = File::ReadBackwards->new('file') or die "can't read 'file' $!"; $lastline = $bw->readline;

    bW

Re: Re: New Line at End File
by sauoq (Abbot) on Dec 10, 2002 at 00:07 UTC

    The special variable $^I not only turns in-place editing on, it also specifies the extension for a backup of the original file. Something like $^I = '.bak' might be better than setting it to '1'. If you really don't want the backup you can set it to an empty string; in-place editing is on unless the variable is undefined.

    -sauoq
    "My two cents aren't worth a dime.";
    
Re: Re: New Line at End File
by Anonymous Monk on Dec 09, 2002 at 22:44 UTC
    Thanks,
    I think I see whats going on, but if you wouldn't mind, can you explain how this works.

    Thanks

      Sure!

      local @ARGV = $file_name; This sets up the file to be read in via perl's command-line magic. It has the same effect as if you had specified the file on the command line to perl. Any subsequent read from <> will come from this opened file.
      local $^I = ''; This has the same effect as the -i command-line switch to perl. It means that when a file is opened for reading via the @ARGV magic, then a subsequent print will go to that same file. Hence "edit in place".
      If you'd like to make a backup of the original file, use some value other than the empty string shown here. The string you give will be used as the extension for the backup. E.g. '.bak'
      Tip o' the hat to sauoq.
      local $/; # sluurp This sets $/ to an undefined value, thus turning off automatic per-line input reading. Any subsequent read from <> (in scalar context) will read all the remaining available input, instead of just the next line.
      local $_ = <>; Here, we finally get around to reading the input. Because of the first and third lines above, $_ will get the entire contents of the named file.
      while ( chomp ) { } Remember that chomp() returns the number of characters chomped off. Since you want to remove any/all newlines at the end of the file, we keep chomping until chomp says it wasn't able to chomp any more.
      print; When all that is done, print the contents of $_ back out to the file, by virtue of $^I being defined.
      Finally, we want to make sure that all those global variables we used aren't munged from the perspective of any other code. (For example, you might have good reason for @ARGV to keep its original values that you passed on the command line.) Therefore, we use local to localize all our changes to the block specified by the curly braces.

      I hope that's clear. If you'd like any further clarification, just ask!

        Thats perfect!

        Thank you very much!

        Does the .bak file need to be removed in the end or does it get removed automatically?
Re: Re: New Line at End File
by tachyon (Chancellor) on Dec 09, 2002 at 23:33 UTC

    seek() and truncate() also work well as shown below....

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print