Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Insert a line at the beginning of a file

Working withText Files

Insert a line at the beginning of a file

by  KevinADC  Posted    (Edited  )
----------------------------
[small]ignore this section:
code
perl
regular expression
print
cgi
command line
backup copy[/small]
----------------------------



Problem:

You want to add a line at the beginning of a file, not the end like append mode '>>' does and you can't use create mode '>' because that deletes any existing lines in the file. Slurping the whole file into an array just to add a line at the beginning of a file is not only unnecessary, it could be impossible if the file is too large to store in memory.

Solution:

Use perls powerful in-place editor. In my opinion this is the best way to edit text files when using perl. It's fast and very simple to use once you know a few basics. And you can hardly go wrong because the in-place editor will even save a backup copy of the original file for you. And editing large files is no problem.

Adding a line to the beginning of a file (prepending):

Code:
[ol]
[li][gray]#!perl[/gray][/li]
[li][link http://perldoc.perl.org/functions/use.html][black][b]use[/b][/black][/link] [green]strict[/green][red];[/red][/li]
[li][black][b]use[/b][/black] [green]warnings[/green][red];[/red][/li]
[li][link http://perldoc.perl.org/functions/my.html][black][b]my[/b][/black][/link] [blue]$file[/blue] = [red]'[/red][purple]path/to/file.txt[/purple][red]'[/red][red];[/red][/li]
[li][black][b]my[/b][/black] [blue]$newline[/blue] = [red]"[/red][purple]In general, if you think something isn't in Perl, try it out, because it usually is.[/purple][red]"[/red][red];[/red] [/li]
[li][red]{[/red][/li]
[li]   [link http://perldoc.perl.org/functions/local.html][black][b]local[/b][/black][/link] [blue]@ARGV[/blue] = [red]([/red][blue]$file[/blue][red])[/red][red];[/red][/li]
[li]   [black][b]local[/b][/black] [blue]$^I[/blue] = [red]'[/red][purple].bac[/purple][red]'[/red][red];[/red][/li]
[li]   [olive][b]while[/b][/olive][red]([/red]<>[red])[/red][red]{[/red][/li]
[li]      [olive][b]if[/b][/olive] [red]([/red][blue]$.[/blue] == [fuchsia]1[/fuchsia][red])[/red] [red]{[/red][/li]
[li]         [link http://perldoc.perl.org/functions/print.html][black][b]print[/b][/black][/link] [red]"[/red][purple][blue]$newline[/blue][blue]$/[/blue][/purple][red]"[/red][red];[/red][/li]
[li]      [red]}[/red][/li]
[li]      [olive][b]else[/b][/olive] [red]{[/red][/li]
[li]         [black][b]print[/b][/black][red];[/red][/li]
[li]      [red]}[/red][/li]
[li]   [red]}[/red][/li]
[li][red]}[/red][/li]
[/ol]

Discussion:

Lines 2 and 3 see below.***

Line 4 is simply the path to your file.

Line 5 is the text to prepend to the file.

Line 6 starts a block of code. The reason for the block is to keep the values of @ARGV and $^I local to the block they are in. @ARGV and $^I are global variables and any value they have can affect (or infect) an entire script. Using the local() function and placing them in a block of code {} creates a temporary value for them that exists only in that block. Once the block is finished their original value (if any) is reissued. This is a good habit to get into when using many of perls global variables.

Line 7 puts $file into the special array @ARGV. Perl uses this array to pass in arguments to programs.

Line 8 is what really makes this all work: [red]$^I[/red] (or $INPLACE_EDIT) tells perl that files processed by the <> construct are to be edited in-place. It's the same as the -i command line switch.

Line 9, the "while(<>){" expression does wonderful things for you. Perl will read from the @ARGV array and pass them into <> as filehandles. Perl opens and closes the files for you. Perl will also send an error to STDERR if a file can't be opened and move onto the next file (if any). You can mass edit many files this way by passing a list in @ARGV to the <> construct.

Line 10 uses another special perl variable: [red]$.[/red] the input record line number variable (or $INPUT_LINE_NUMBER). This is a read only value. It lets you know which line number of the file is about to be processed. So we need only check and see if $. == 1 and of it does print the new line. The new line is now at the beginning of the file.

In line 11 we see yet another special perl variable: $/, the input record seperator (or $INPUT_RECORD_SEPARATOR). The value of $/ is generally "\n" a newline. But on some systems it coud be "\r\n" or even something else. You could use \n in place of $/ and most operating sytems (including windows) will be fine with that.

The rest of the lines tells perl to print the original lines back into the file. If the "else{}" block was not there, perl would have only printed our new line to the file and not printed anything else.

Using perls in-place editor will open new doors of possibilites to you if you have never used it. Tasks that
previously had you jumping through hoops can generally be done fast and easy using the in-place editor.


*** Pragmas (perl 5.8.8) used in example code :
[ul]
[li][link http://perldoc.perl.org/strict.html]strict[/link] - Perl pragma to restrict unsafe constructs[/li]
[li][link http://perldoc.perl.org/warnings.html]warnings[/link] - Perl pragma to control optional warnings[/li]
[/ul]

Code without markup:

Code:
#!perl
use strict;
use warnings;
my $file = 'path/to/file.txt';
my $newline = "In general, if you think something isn't in Perl, try it out, because it usually is."; 
{
   local @ARGV = ($file);
   local $^I = '.bac';
   while(<>){
      if ($. == 1) {
         print "$newline$/";
      }
      else {
         print;
      }
   }
}
Register to rate this FAQ  : BAD 1 2 3 4 5 6 7 8 9 10 GOOD
Please Note: 1 is Bad, 10 is Good :-)

Part and Inventory Search

Back
Top