在re.match上循环

时间:2016-08-22 08:40:44

标签: regex python-3.x while-loop

我有下面的代码,我希望while循环部分作为手动测试,即它应该用*替换任何单词内部字符并保留边框字符

    # manual testing 
    r = re.compile(r'(\w[*]*)(\w)(\w+)')
    rtext = r.sub(r'\1*\3', 'mon texste')
    print(rtext)
    rtext = r.sub(r'\1*\3', rtext)
    print(rtext)
    rtext = r.sub(r'\1*\3', rtext)
    print(rtext)
    rtext = r.sub(r'\1*\3', rtext)
    print(rtext)
    rtext = r.sub(r'\1*\3', rtext)
    print(rtext)

    text = "mon test is here"
    # Loop testing, :( it works once et doesn't iterate !!!
    while(r.match(text) is not None):
        print(text, type(r.match(text)))# just to check 
        text = r.sub(r'\1*\3',text)
    print(text)

3 个答案:

答案 0 :(得分:0)

re.match仅匹配字符串开头的字符;你应该使用re.search代替。 (docs)

因此,请将循环条件中的r.match更改为r.search

while(r.search(text) is not None):
    text = r.sub(r'\1*\3',text)
print(text)

此代码工作正常。

答案 1 :(得分:0)

这里不需要循环,你可以使用一个带有3个捕获组的简单正则表达式,并在re.sub替换参数中使用lambda用星号替换中间部分。

import re
r2 = re.compile(r"\b(\w)(\w*)(\w)\b")
res = r2.sub(lambda m: "{0}{1}{2}".format(m.group(1), "*"*len(m.group(2)), m.group(3)), 'mon texste')

请参阅Python demo

模式详情

  • \b - 领先的字边界
  • (\w) - 第1组:主要字词char
  • (\w*) - 第2组:零个或多个字词
  • (\w) - 第3组:尾随字词char
  • \b - 尾随字边界

替换:

  • "{0}{1}{2}".format() - 构建3组
  • 的结果
  • m.group(1) - 主要词汇char
  • "*"*len(m.group(2)) - *倍于第二组的长度
  • m.group(3) - 尾随字词char

答案 2 :(得分:0)

正如xmcp已经说过的那样,你正在使用re.match并且总是尝试在字符串的开头匹配,所以你必须改为使用re.search

请注意,循环不必要地经常运行正则表达式。您可以通过存储匹配对象然后在没有正则表达式的情况下执行实际替换来更改它,例如,使用标准字符串操作:

m = r.search(text)
while m:
    inner = '*' * (m.end() - m.start() - 2)
    text = text[:m.start() + 1] + inner + text[m.end() - 1:]
    m = r.search(text)

这使用匹配的索引来修补字符串。

您还可以使用单个正则表达式执行替换,该表达式使用一些后视和前瞻魔术来查找内部字符:

>>> text = 'mon test is here'
>>> re.sub('(?<!^)(?<!\s)\w(?!\s|$)', '*', text)
'm*n t**t is h**e'