packing things back to regular expression
Paul McGuire
ptmcg at austin.rr.com
Thu Feb 21 16:29:49 EST 2008
On Feb 20, 6:29 pm, Steven D'Aprano <st... at REMOVE-THIS-
cybersource.com.au> wrote:
> On Wed, 20 Feb 2008 11:36:20 -0800, Amit Gupta wrote:
> > Before I read the message: I screwed up.
>
> > Let me write again
>
> >>> x = re.compile("CL(?P<name1>[a-z]+)")
> > # group name "name1" is attached to the match of lowercase string of
> > alphabet
> > # Now I have a dictionary saying {"name1", "iamgood"}
> > # I would like a function, that takes x and my dictionary and
> > return "CLiamgood"
> > # If my dictionary instead have {"name1", "123"}, it gives error on
> > processingit
> > #
> > # In general, I have reg-expression where every non-trivial match has a
> > group-name. I want to do the reverse of reg-exp match. The function can
> > take reg-exp and replace the group-matches from dictionary
> > # I hope, this make it clear.
>
<snip>
>
> Good luck.
>
> --
> Steven
Oh, pshaw! Try this pyparsing ditty.
-- Paul
http://pyparsing.wikispaces.com
from pyparsing import *
import re
# replace patterns of (?P<name>xxx) with dict
# values iff value matches 'xxx' as re
LPAR,RPAR,LT,GT = map(Suppress,"()<>")
nameFlag = Suppress("?P")
rechars = printables.replace(")","").replace("(","")+" "
regex = Forward()("fld_re")
namedField = (nameFlag + \
LT + Word(alphas,alphanums+"_")("fld_name") + GT + \
regex )
regex << Combine(OneOrMore(Word(rechars) |
r"\(" | r"\)" |
nestedExpr(LPAR, RPAR, namedField |
regex,
ignoreExpr=None ) ))
def fillRE(reString, nameDict):
def fieldPA(tokens):
fieldRE = tokens.fld_re
fieldName = tokens.fld_name
if fieldName not in nameDict:
raise ParseFatalException(
"name '%s' not defined in name dict" %
(fieldName,) )
fieldTranslation = nameDict[fieldName]
if (re.match(fieldRE, fieldTranslation)):
return fieldTranslation
else:
raise ParseFatalException(
"value '%s' does not match re '%s'" %
(fieldTranslation, fieldRE) )
namedField.setParseAction(fieldPA)
try:
return (LPAR + namedField + RPAR).transformString(reString)
except ParseBaseException, pe:
return pe.msg
# tests start here
testRE = r"CL(?P<name1>[a-z]+)"
# a simple test
test1 = { "name1" : "iamgood" }
print fillRE(testRE, test1)
# harder test, including nested names (have to be careful in
# constructing the names dict)
testRE = \
r"CL(?P<name1>[a-z]+)XY(?P<name4>(:?AB)[aeiou]+)" \
r"(?P<name2>CD(?P<name3>..)\?EF)"
test3 = { "name1" : "iamgoodZ",
"name2" : "CD@@?EF",
"name3" : "@@",
"name4" : "ABeieio",
}
print fillRE(testRE, test3)
# test a non-conforming field
test2 = { "name1" : "123" }
print fillRE(testRE, test2)
Prints:
CLiamgood
CLiamgoodZXYABeieioCD@@?EF
value '123' does not match re '[a-z]+'
More information about the Python-list
mailing list