這是一個使用pyparsing的解決方案。我知道你特別詢問了一個正則表達式解決方案,但是如果你的需求改變了,你可能會發現擴展一個pyparsing解析器更容易。或者pyparsing原型解決方案可能會讓您更深入地瞭解導致正則表達式或其他最終實現的問題。
src = """\
Hello
REPLACE(str1) this is to replace
REPLACE(str2) this is to replace
"""
from pyparsing import Suppress, Word, alphas, alphanums, restOfLine
LPAR,RPAR = map(Suppress,"()")
ident = Word(alphas, alphanums)
replExpr = "REPLACE" + LPAR + ident("name") + RPAR + restOfLine("body")
replExpr.setParseAction(
lambda toks : '<replace name="%(name)s">%(body)s </replace>' % toks
)
print replExpr.transformString(src)
在這種情況下,您可以創建與pyparsing匹配的表達,定義解析動作做的文本轉換,然後調用transformString通過輸入源進行掃描,以發現所有的比賽,應用解析對每個匹配採取行動,並返回結果輸出。解析動作與@ steveha解決方案中的mksub具有類似的功能。
除了解析動作之外,pyparsing還支持命名錶達式的各個元素 - 我使用「name」和「body」來標記感興趣的兩個部分,它們在re解決方案中表示爲組1和2你可以在重新名組,相應的重新會是什麼樣子:
s_pat = "^\s*REPLACE\((?P<name>[^)]+)\)(?P<body>.*)$"
不幸的是,通過名字來訪問這些羣體,你必須調用重新匹配對象的group()
方法,你可以」 t直接執行命名的字符串插值,就像在我的lambda分析操作中一樣。但是這是Python,對吧?我們可以換一個類可贖回,這將使我們的名字到組類似字典的訪問:
class CallableDict(object):
def __init__(self,fn):
self.fn = fn
def __getitem__(self,name):
return self.fn(name)
def mksub(m):
return '<replace name="%(name)s">%(body)s</replace>' % CallableDict(m.group)
s_output = re.sub(pat, mksub, s_input)
使用CallableDict
,在mksub串插現在可以調用m.group每個字段,通過使它看起來我們正在檢索字典的['name']和['body']元素。