• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#! /usr/bin/env python3
2
3"""Reverse grep.
4
5Usage: rgrep [-i] pattern file
6"""
7
8import sys
9import re
10import getopt
11
12
13def main():
14    bufsize = 64 * 1024
15    reflags = 0
16    opts, args = getopt.getopt(sys.argv[1:], "i")
17    for o, a in opts:
18        if o == '-i':
19            reflags = reflags | re.IGNORECASE
20    if len(args) < 2:
21        usage("not enough arguments")
22    if len(args) > 2:
23        usage("exactly one file argument required")
24    pattern, filename = args
25    try:
26        prog = re.compile(pattern, reflags)
27    except re.error as msg:
28        usage("error in regular expression: %s" % msg)
29    try:
30        f = open(filename)
31    except IOError as msg:
32        usage("can't open %r: %s" % (filename, msg), 1)
33    with f:
34        f.seek(0, 2)
35        pos = f.tell()
36        leftover = None
37        while pos > 0:
38            size = min(pos, bufsize)
39            pos = pos - size
40            f.seek(pos)
41            buffer = f.read(size)
42            lines = buffer.split("\n")
43            del buffer
44            if leftover is None:
45                if not lines[-1]:
46                    del lines[-1]
47            else:
48                lines[-1] = lines[-1] + leftover
49            if pos > 0:
50                leftover = lines[0]
51                del lines[0]
52            else:
53                leftover = None
54            for line in reversed(lines):
55                if prog.search(line):
56                    print(line)
57
58
59def usage(msg, code=2):
60    sys.stdout = sys.stderr
61    print(msg)
62    print(__doc__)
63    sys.exit(code)
64
65
66if __name__ == '__main__':
67    main()
68