#!/usr/bin/perl -w # rp pat rpl file... # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # This program takes a perl pattern and scans thru the files for it. When it # is found, the file is "edited" so that all instances of the pattern $pat # are replaced by the string $rpl. The editing is done "in place", by copying # the text over to a /tmp/ file, and if any matches succeed, the /tmp/ file # is copied back to the original file. This method is like ed, and works for # multiply-linked files. It also doesn't touch files that don't contain the # pattern, so make still works properly. At present, there is no provision # for making a backup copy, but it'd be easy enough to do if needed. # # Note some special cases, based on the name that we're called by: # frp matches only function calls, i.e., /\b$pat\s*\(/. # vrp matches "variables", i.e., /\b$pat\b/ # If called by any other name will merely replace $pat with $rpl globally. # # We show the file names and the matches. Perhaps we need a -v option ... # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # ($P = $0) =~ s/.*\///; $Usage = "Usage: $P pattern replacement [filename]...\n"; # # Check out the name we were called with: # $p1 = $p2 = $r1 = $r2 = ''; if (lc($P) eq 'frp') { # frp matches function calls. $p1 = '\b'; $p2 = '\s*\('; $r2 = '('; } elsif (lc($P) eq 'vrp') { # vrp matches variables. $p1 = '\b'; $p2 = '\b'; } $, = ' '; defined($pat = shift) || die $Usage; defined($rpl = shift) || die $Usage; for $f (@ARGV) { if ($f) { # print "File : $f\n"; if (open(F,"<$f")) { $t = "/tmp/fr_$$"; if (open(T,">$t")) { $m = 0; # Number of matches. while () { if (s/$p1$pat$p2/$r1$rpl$r2/g) { print; ++$m; } print T; } close(F); close(T); if ($m) { print "=====> $f\n"; system "cp $t $f"; } system "rm $t"; } else { printf STDERR "Can't write \"$t\"\n"; } } else { printf STDERR "Can't read \"$f\"\n"; } } }