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.
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]+'