You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

66 lines
1.4 KiB

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