Python正则表达式替换除特定单词之外的所有内容

时间:2016-07-06 09:58:32

标签: python regex

我正在尝试使用正则表达式执行以下

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_'

2 个答案:

答案 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的第二个参数传递,并将_与要匹配的匹配字符串的长度相乘。