Syntactic Confectionery Delight | |
PerlMonks |
How do I change one line in a file/delete a line in a file/insert a line in the middle of a file/append to the beginning of a file?by faq_monk (Initiate) |
on Oct 08, 1999 at 00:23 UTC ( [id://645]=perlfaq nodetype: print w/replies, xml ) | Need Help?? |
Current Perl documentation can be found at perldoc.perl.org. Here is our local, out-dated (pre-5.6) version: Although humans have an easy time thinking of a text file as being a sequence of lines that operates much like a stack of playing cards -- or punch cards -- computers usually see the text file as a sequence of bytes. In general, there's no direct way for Perl to seek to a particular line of a file, insert text into a file, or remove text from a file.
(There are exceptions in special circumstances. You can add or remove at
the very end of the file. Another is replacing a sequence of bytes with
another sequence of the same length. Another is using the The general solution is to create a temporary copy of the text file with the changes you want, then copy that over the original. This assumes no locking.
$old = $file; $new = "$file.tmp.$$"; $bak = "$file.bak";
open(OLD, "< $old") or die "can't open $old: $!"; open(NEW, "> $new") or die "can't open $new: $!";
# Correct typos, preserving case while (<OLD>) { s/\b(p)earl\b/${1}erl/i; (print NEW $_) or die "can't write to $new: $!"; }
close(OLD) or die "can't close $old: $!"; close(NEW) or die "can't close $new: $!";
rename($old, $bak) or die "can't rename $old to $bak: $!"; rename($new, $old) or die "can't rename $new to $old: $!";
Perl can do this sort of thing for you automatically with the
# Renumber a series of tests from the command line perl -pi -e 's/(^\s+test\s+)\d+/ $1 . ++$count /e' t/op/taint.t
# form a script local($^I, @ARGV) = ('.bak', glob("*.c")); while (<>) { if ($. == 1) { print "This line should appear at the top of each file\n"; } s/\b(p)earl\b/${1}erl/i; # Correct typos, preserving case print; close ARGV if eof; # Reset $. } If you need to seek to an arbitrary line of a file that changes infrequently, you could build up an index of byte positions of where the line ends are in the file. If the file is large, an index of every tenth or hundredth line end would allow you to seek and read fairly efficiently. If the file is sorted, try the look.pl library (part of the standard perl distribution).
In the unique case of deleting lines at the end of a file, you can use
open (FH, "+< $file"); while ( <FH> ) { $addr = tell(FH) unless eof(FH) } truncate(FH, $addr); Error checking is left as an exercise for the reader.
|
|