Home
Search Perl pages
Subjects
By activity
Professions, Sciences, Humanities, Business, ...
User Interface
Text-based, GUI, Audio, Video, Keyboards, Mouse, Images,...
Text Strings
Conversions, tests, processing, manipulation,...
Math
Integer, Floating point, Matrix, Statistics, Boolean, ...
Processing
Algorithms, Memory, Process control, Debugging, ...
Stored Data
Data storage, Integrity, Encryption, Compression, ...
Communications
Networks, protocols, Interprocess, Remote, Client Server, ...
Hard World Timing, Calendar and Clock, Audio, Video, Printer, Controls...
File System
Management, Filtering, File & Directory access, Viewers, ...
|
|
|
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. Replacing a sequence of
bytes with another sequence of the same length is one. Another is using the $DB_RECNO array bindings as documented in DB_File. Yet another is manipulating files with all lines the same length.)
The general solution is to create a temporary copy of the text file with
the changes you want, then copy that over the original.
$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 -i
command-line switch or the closely-related $^I variable (see
the perlrun manpage for more details). Note that
-i may require a suffix on some non-Unix systems; see the platform-specific
documentation that came with your port.
# 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
tell() and truncate(). The following code snippet
deletes the last line of a file without making a copy or reading the whole
file into memory:
open (FH, "+< $file");
while ( <FH> ) { $addr = tell(FH) unless eof(FH) }
truncate(FH, $addr);
Error checking is left as an exercise for the reader.
Source: Perl FAQ: Files and Formats Copyright: Copyright (c) 1997 Tom Christiansen and Nathan Torkington. |
Next: How do I count the number of lines in a file?
Previous: How do I flush/unbuffer a filehandle? Why must I do this?
(Corrections, notes, and links courtesy of RocketAware.com)
Up to: File Access
Rapid-Links:
Search | About | Comments | Submit Path: RocketAware > Perl >
perlfaq5/How_do_I_change_one_line_in_a_fi.htm
RocketAware.com is a service of Mib Software Copyright 2000, Forrest J. Cavalier III. All Rights Reserved. We welcome submissions and comments
|