|
1 #! /usr/bin/env python |
|
2 |
|
3 # Update a bunch of files according to a script. |
|
4 # The input file contains lines of the form <filename>:<lineno>:<text>, |
|
5 # meaning that the given line of the given file is to be replaced |
|
6 # by the given text. This is useful for performing global substitutions |
|
7 # on grep output: |
|
8 |
|
9 import os |
|
10 import sys |
|
11 import re |
|
12 |
|
13 pat = '^([^: \t\n]+):([1-9][0-9]*):' |
|
14 prog = re.compile(pat) |
|
15 |
|
16 class FileObj: |
|
17 def __init__(self, filename): |
|
18 self.filename = filename |
|
19 self.changed = 0 |
|
20 try: |
|
21 self.lines = open(filename, 'r').readlines() |
|
22 except IOError, msg: |
|
23 print '*** Can\'t open "%s":' % filename, msg |
|
24 self.lines = None |
|
25 return |
|
26 print 'diffing', self.filename |
|
27 |
|
28 def finish(self): |
|
29 if not self.changed: |
|
30 print 'no changes to', self.filename |
|
31 return |
|
32 try: |
|
33 os.rename(self.filename, self.filename + '~') |
|
34 fp = open(self.filename, 'w') |
|
35 except (os.error, IOError), msg: |
|
36 print '*** Can\'t rewrite "%s":' % self.filename, msg |
|
37 return |
|
38 print 'writing', self.filename |
|
39 for line in self.lines: |
|
40 fp.write(line) |
|
41 fp.close() |
|
42 self.changed = 0 |
|
43 |
|
44 def process(self, lineno, rest): |
|
45 if self.lines is None: |
|
46 print '(not processed): %s:%s:%s' % ( |
|
47 self.filename, lineno, rest), |
|
48 return |
|
49 i = eval(lineno) - 1 |
|
50 if not 0 <= i < len(self.lines): |
|
51 print '*** Line number out of range: %s:%s:%s' % ( |
|
52 self.filename, lineno, rest), |
|
53 return |
|
54 if self.lines[i] == rest: |
|
55 print '(no change): %s:%s:%s' % ( |
|
56 self.filename, lineno, rest), |
|
57 return |
|
58 if not self.changed: |
|
59 self.changed = 1 |
|
60 print '%sc%s' % (lineno, lineno) |
|
61 print '<', self.lines[i], |
|
62 print '---' |
|
63 self.lines[i] = rest |
|
64 print '>', self.lines[i], |
|
65 |
|
66 def main(): |
|
67 if sys.argv[1:]: |
|
68 try: |
|
69 fp = open(sys.argv[1], 'r') |
|
70 except IOError, msg: |
|
71 print 'Can\'t open "%s":' % sys.argv[1], msg |
|
72 sys.exit(1) |
|
73 else: |
|
74 fp = sys.stdin |
|
75 curfile = None |
|
76 while 1: |
|
77 line = fp.readline() |
|
78 if not line: |
|
79 if curfile: curfile.finish() |
|
80 break |
|
81 n = prog.match(line) |
|
82 if n < 0: |
|
83 print 'Funny line:', line, |
|
84 continue |
|
85 filename, lineno = prog.group(1, 2) |
|
86 if not curfile or filename <> curfile.filename: |
|
87 if curfile: curfile.finish() |
|
88 curfile = FileObj(filename) |
|
89 curfile.process(lineno, line[n:]) |
|
90 |
|
91 if __name__ == "__main__": |
|
92 main() |