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