1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
|
#! /usr/bin/python
# -*- coding: utf-8 -*-
# @creator (C) 2003 Guido U. Draheim
# @license http://creativecommons.org/licenses/by-nc-sa/2.0/de/
from __future__ import print_function
import re
try:
basestring
except NameError:
basestring = str
# ---------------------------------------------------------- Regex Match()
# beware, stupid python interprets backslashes in replace-parts only partially!
class MatchReplace:
""" A MatchReplace is a mix of a Python Pattern and a Replace-Template """
def __init__(self, matching, template, count = 0, flags = None):
""" setup a substition from regex 'matching' into 'template',
the replacement count default of 0 will replace all occurrences.
The first argument may be a Match object or it is a string that
will be turned into one by using Match(matching, flags). """
self.template = template
MatchReplace.__call__(self, matching, template, count, flags)
def __call__(self, matching, template = None, count = 0, flags = None):
""" other than __init__ the template may be left off to be unchanged"""
if isinstance(count, basestring): # count/flags swapped over?
flags = count; count = 0
if isinstance(matching, Match):
self.matching = matching
else:
self.matching = Match()(matching, flags) ## python 2.4.2 bug
if template is not None:
self.template = template
self.count = count
def __and__(self, string):
""" z = MatchReplace('foo', 'bar') & 'foo'; assert z = 'bar' """
text, self.matching.replaced = \
self.matching.regex.subn(self.template, string, self.count)
return text
def __rand__(self, string):
""" z = 'foo' & Match('foo') >> 'bar'; assert z = 'bar' """
text, self.matching.replaced = \
self.matching.regex.subn(self.template, string, self.count)
return text
def __iand__(self, string):
""" x = 'foo' ; x &= Match('foo') >> 'bar'; assert x == 'bar' """
string, self.matching.replaced = \
self.matching.regex.subn(self.template, string, self.count)
return string
def __rshift__(self, count):
" shorthand to set the replacement count: Match('foo') >> 'bar' >> 1 "
self.count = count ; return self
def __rlshift__(self, count):
self.count = count ; return self
class Match:
""" A Match is actually a mix of a Python Pattern and MatchObject """
def __init__(self, pattern = None, flags = None):
""" flags is a string: 'i' for case-insensitive etc.; it is just
short for a regex prefix: Match('foo','i') == Match('(?i)foo') """
Match.__call__(self, pattern, flags)
def __call__(self, pattern, flags = None):
assert isinstance(pattern, str) or pattern is None
assert isinstance(flags, str) or flags is None
self.replaced = 0 # set by subn() inside MatchReplace
self.found = None # set by search() to a MatchObject
self.pattern = pattern
if pattern is not None:
if flags:
self.regex = re.compile("(?"+flags+")"+self.pattern)
else:
self.regex = re.compile(self.pattern)
return self
def __repr__(self):
return self.pattern
def __truth__(self):
return self.found is not None
def __and__(self, string):
self.found = self.regex.search(string)
return self.__truth__()
def __rand__(self, string):
self.found = self.regex.search(string)
return self.__truth__()
def __rshift__(self, template):
return MatchReplace(self, template)
def __rlshift__(self, template):
return MatchReplace(self, template)
def __getitem__(self, index):
return self.group(index)
def group(self, index):
assert self.found is not None
return self.found.group(index)
def finditer(self, string):
return self.regex.finditer(string)
if __name__ == "__main__":
# matching:
if "foo" & Match("oo"):
print("oo")
x = Match()
if "foo" & x("(o+)"):
print(x[1])
# replacing:
y = "fooboo" & Match("oo") >> "ee"
print(y)
r = Match("oo") >> "ee"
print("fooboo" & r)
s = MatchReplace("oo", "ee")
print("fooboo" & s)
|