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.
108 lines
4.2 KiB
108 lines
4.2 KiB
#! /usr/bin/env python3 |
|
|
|
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)
|
|
|