2009-05-20 30 views
4

长话短说,我有两个正则表达式模式。一个模式匹配我想要替换的事物,另一个模式匹配那些不应该被替换的模式的特例。举个简单的例子,假设第一个是“\ {。* \}”,第二个是“\ {\ {。* \} \}”。然后应该替换“{this}”,但“{{this}}”不应该。有没有简单的方法来取一个字符串,并说“只要第一个字符串的所有实例都替换为”hello“,只要它不匹配第二个字符串”?仅当它与另一个正则表达式(Python)不匹配时才替换正则表达式

换句话说,有没有办法让一个正则表达式“匹配第一个字符串,而不是第二个”很容易不修改第一个字符串?我知道我可以手动修改我的第一个正则表达式,从不匹配第二个正则表达式的实例,但是随着第一个正则表达式变得更加复杂,变得非常困难。

回答

4

你可以给替换函数(reference

但要确保第一个正则表达式包含第二个。这只是一个例子:

regex1 = re.compile('\{.*\}') 
regex2 = re.compile('\{\{.*\}\}') 

def replace(match): 
    match = match.group(0) 
    if regex2.match(match): 
     return match 
    return 'replacement' 


regex1.sub(replace, data) 
1

您可以用替换字符串(将包括{{}}个字符串替换所有{}实例,然后用对其自身的后向引用替换{{}}(将第一个替换替换为原始数据) - 那么只有{}实例会发生变化。

+0

你能给我一个如何在Python中做到这一点的例子吗?我不太清楚我的理解。谢谢! – So8res 2009-05-20 16:56:55

+0

我可以在大约一个小时内,但不是现在,对不起... – 2009-05-20 16:58:45

0

这在我看来是次优来匹配两个不同的正则表达式,当你在寻找什么是真正的一个模式。为了说明:

import re 
foo = "{{this}}" 
bar = "{that}" 
re.match("\{[^\{].*[^\}]\}", foo) # gives you nothing 
re.match("\{[^\{].*[^\}]\}", bar) # gives you a match object 

所以这真的是你的正则表达式,可能会更精确一点。

6

使用负前瞻/后面断言

pattern = re.compile("(?<!\{)\{(?!\{).*?(?<!\})\}(?!\})") 
pattern.sub("hello", input_string) 

负前瞻/后面断言允许您比较多的字符串,但不被视为使用了字符串的一部分的比赛。在断言之前还有一个正常的查看,只有当字符串IS在给定模式后面/之前时,才会使字符串匹配。

这是混淆找了一下,在这里它是在片:

"(?<!\{)" #Not preceded by a { 
"\{"  #A { 
"(?!\{)" #Not followed by a { 
".*?"  #Any character(s) (non-greedy) 
"(?<!\})" #Not preceded by a } (in reference to the next character) 
"\}"  #A } 
"(?!\})" #Not followed by a } 

所以,我们正在寻找一个{周围没有任何其他{的,其次是一些字符,然后是}没有任何其他的}围绕它。

通过使用负前视/后置断言,我们将其压缩为单个正则表达式,该表达式将成功匹配字符串中任何位置的单个{}。

另外,请注意*是一个贪婪的运算符。它将尽可能匹配。如果您使用"\{.*\}",并且文本中有多个{}块,则它们之间的所有内容都将与其一起进行处理。

“这是一些示例文本{块1}更多文本,看着我消失{块2}甚至更多的文本”

成为

“这是一些示例文本你好甚至更多而不是文字”

“这是一些示例文本你好更多文本,看着我消失你好甚至更多的文本”

要得到我们需要使其非贪婪通过附加一个适当的输出?

python文档在呈现re库方面做得很好,但真正学习的唯一方法是进行实验。