Main Page |
Recipe 7.16 Modifying a File in Place with the -i Switch7.16.1 ProblemYou need to modify a file in place from the command line, and you're too lazy[5] for the file manipulation of Recipe 7.15.
7.16.2 SolutionUse the -i and -p switches to Perl. Write your program on the command line: % perl -i.orig -p -e 'FILTER COMMAND' file1 file2 file3 ... or use the switches in programs: #!/usr/bin/perl -i.orig -p # filter commands go here 7.16.3 DiscussionThe -i command-line switch modifies each file in place. It creates a temporary file as in the previous recipe, but Perl takes care of the tedious file manipulation for you. Use it with -p (explained in Recipe 7.14) to turn: while (<>) { if ($ARGV ne $oldargv) { # are we at the next file? rename($ARGV, $ARGV . ".orig"); open(ARGVOUT, ">", $ARGV); # plus error check select(ARGVOUT); $oldargv = $ARGV; } s/DATE/localtime/e; } continue{ print; } select (STDOUT); # restore default output into: % perl -pi.orig -e 's/DATE/localtime/e' The -i switch takes care of making a backup (say -i instead of -i.orig to discard the original file contents instead of backing them up), and -p makes Perl loop over filenames given on the command line (or STDIN if no files were given). The preceding one-liner would turn a file containing the following: Dear Sir/Madam/Ravenous Beast, As of DATE, our records show your account is overdue. Please settle by the end of the month. Yours in cheerful usury, --A. Moneylender into: Dear Sir/Madam/Ravenous Beast, As of Sat Apr 25 12:28:33 1998, our records show your account is overdue. Please settle by the end of the month. Yours in cheerful usury, --A. Moneylender This switch makes in-place translators a lot easier to write and to read. For instance, this changes isolated instances of "hisvar" to "hervar" in all C, C++, and yacc files: % perl -i.old -pe 's{\bhisvar\b}{hervar}g' *.[Cchy] Turn on and off the -i behavior with the special variable $^I. Set @ARGV, and then use <> as you would with -i on the command line: # set up to iterate over the *.c files in the current directory, # editing in place and saving the old file with a .orig extension local $^I = ".orig"; # emulate -i.orig local @ARGV = glob("*.c"); # initialize list of files while (<>) { if ($. = = 1) { print "This line should appear at the top of each file\n"; } s/\b(p)earl\b/${1}erl/ig; # Correct typos, preserving case print; } continue {close ARGV if eof} Beware that creating a backup file under a particular name when that name already exists clobbers the version previously backed up. 7.16.4 See Alsoperlrun(1), and the "Switches" section of Chapter 19 of Programming Perl; the $^I and $. variables in perlvar(1), and in Chapter 28 of Programming Perl; the .. operator in the "Range Operator" sections of perlop(1) and Chapter 3 of Programming Perl |
Main Page |