From perlfaq5 the answer to How do I change, delete or insert a line in a file, or add to the beginning of a file?
The basic idea of inserting, changing, or deleting a line from a text file is to read and print the file to the point where you want to make changes, make changes, then read and print the rest of the file. Perl does not provide random access to strings (all the more so since the entry separator, $ /, has been changed), although modules such as Tie :: File can fake it.
The Perl program for these tasks takes the basic form of opening a file, printing its lines and closing the file:
open my $in, '<', $file or die "Can't read old file: $!"; open my $out, '>', "$file.new" or die "Can't write new file: $!"; while( <$in> ) { print $out $_; }
close $ out; In this basic form, add the parts you need to insert, modify, or delete rows.
To add lines to the beginning, print these lines before entering a loop that prints existing lines.
open my $in, '<', $file or die "Can't read old file: $!"; open my $out, '>', "$file.new" or die "Can't write new file: $!"; print $out "# Add this line to the top\n";
close $ out; To modify existing rows, insert code to modify rows within a while loop. In this case, the code finds all lower versions of "perl" and upper case. This happens for every line, so make sure you do this on every line!
open my $in, '<', $file or die "Can't read old file: $!"; open my $out, '>', "$file.new" or die "Can't write new file: $!"; print $out "# Add this line to the top\n"; while( <$in> ) { s/\b(perl)\b/Perl/g; print $out $_; }
close $ out; To change only a specific line, it is useful to use the input line number $. First read and print the lines to the ones you want to change. Then read the one line you want to change, change it and print. After that, read the rest of the lines and print them:
while( <$in> ) # print the lines before the change { print $out $_; last if $. == 4; # line number before change } my $line = <$in>; $line =~ s/\b(perl)\b/Perl/g; print $out $line; while( <$in> ) # print the rest of the lines { print $out $_; }
To skip lines, use loop controls. The next one in this example skips the comment lines, and the last one stops all processing when it encounters either END or DATA .
while( <$in> ) { next if /^\s+#/;
Do the same to delete a specific line using the following command to skip lines that you do not want to display in the output. This example skips every fifth line:
while( <$in> ) { next unless $. % 5; print $out $_; }
If for some odd reason you really want to see the entire file at the same time, and not process it in turn, you can split it (for now, you can put all this into memory!):
open my $in, '<', $file or die "Can't read old file: $!" open my $out, '>', "$file.new" or die "Can't write new file: $!"; my @lines = do { local $/; <$in> };
Modules such as File :: Slurp and Tie :: File can also help with this. However, if you cannot read the entire file at once. Perl does not return this memory to the operating system until the process is complete.
You can also use single-line Perl to modify the file in place. The following changes all “Fred” to “Barney” in inFile.txt, overwriting the file with the new contents. Using the -p switch, Perl ends the while loop with the code specified with -e, and -i enables in-place editing. The current line is in $. With -p, Perl automatically prints the $ value at the end of the loop. See Perlrun for more details.
perl -pi -e 's/Fred/Barney/' inFile.txt
To backup inFile.txt, give the -i file extension to add:
perl -pi.bak -e 's/Fred/Barney/' inFile.txt
To change only the fifth line, you can add the verification check $., The line number of the input, and then only perform the operation when the test passes:
perl -pi -e 's/Fred/Barney/ if $. == 5' inFile.txt
To add lines to a specific line, you can add a line (or lines!) Before Perl prints $ _:
perl -pi -e 'print "Put before third line\n" if $. == 3' inFile.txt
You can even add a line to the beginning of the file, as the current line prints at the end of the loop:
perl -pi -e 'print "Put before first line\n" if $. == 1' inFile.txt
To insert a line after one into the file, use the -n switch. This is exactly the same as -p, except that it does not print $ _ at the end of the loop, so you have to do it yourself. In this case, print $ _ first, then print the line you want to add.
perl -ni -e 'print; print "Put after fifth line\n" if $. == 5' inFile.txt
To delete lines, print only the ones you want.
perl -ni -e 'print unless /d/' inFile.txt ... or ... perl -pi -e 'next unless /d/' inFile.txt