我正在尝试使用正则表达式执行以下 :
import re
x = re.compile('[^(going)|^(you)]') # words to replace
s = 'I am going home now, thank you.' # string to modify
print re.sub(x, '_', s)
我得到的结果是:
'_____going__o___no______n__you_'
我想要的结果是:
'_____going_________________you_'
由于^
只能在括号[]
中使用,因此这个结果很有意义,但我不确定该怎么做。
我甚至试过了'([^g][^o][^i][^n][^g])|([^y][^o][^u])'
,但它产生了'_g_h___y_'
。
答案 0 :(得分:5)
不像第一次出现那么容易,因为没有"没有"在RE ^
内的[ ]
内只有一个字符匹配(如您所见)。这是我的解决方案:
import re
def subit(m):
stuff, word = m.groups()
return ("_" * len(stuff)) + word
s = 'I am going home now, thank you.' # string to modify
print re.sub(r'(.+?)(going|you|$)', subit, s)
给出:
_____going_________________you_
解释。 RE本身(我总是使用原始字符串)匹配任何字符(.+
)中的一个或多个,但是非贪婪(?
)。这是在第一个括号组(括号)中捕获的。接下来是"去"或者"你"或行尾($
)。
subit
是一个函数(你可以在合理范围内调用它),每个替换都会调用它。传递匹配对象,我们可以从中检索捕获的组。第一组我们只需要长度,因为我们用下划线替换每个字符。返回的字符串将替换匹配模式的字符串。
答案 1 :(得分:3)
这是一种正则表达式方法:
>>> re.sub(r'(?!going|you)\b([\S\s]+?)(\b|$)', lambda x: (x.end() - x.start())*'_', s)
'_____going_________________you_'
这个想法是,当你处理单词并且想要排除它们等时,你需要记住大多数正则表达式引擎(大多数使用传统的NFA)按字符分析字符串。在这里,因为你想要排除两个单词并想要使用否定前瞻,你需要将允许的字符串定义为单词(使用单词边界),因为在sub中它用匹配的替换字符串替换匹配的模式,你不能只是通过_
因为在这种情况下,它会将I am
之类的部分替换为3个下划线(I
,'','am')。因此,您可以使用函数作为sub的第二个参数传递,并将_
与要匹配的匹配字符串的长度相乘。