python中的re.sub并不总是替换字符串

时间:2012-10-19 14:48:01

标签: python regex python-2.7

当我尝试用另一个字符串替换字符串时,re.sub方法并不总是这样。

sentence = '<date>2004/12/01</date>T09:38:27+01:00'+
           'Wed, <date>2012/9/05</date> 10:55:17 UTC %3C%3C%3C'

time_identifier = u'(?<=[\s\.,T])([\d]{2}[:]{1}[\d]{2}([:]{1}[\d]{2})*[\s\.,+]*(UTC|GMT|CEST|EDT|IST|BST)*(\d\d:\d\d)*)(?=[\s\.,T]|\Z)|'\
                  u'(?<=\A)([\d]{2}[:]{1}[\d]{2}([:]{1}[\d]{2})*[\s\.,+]*(UTC|GMT|CEST|EDT|IST|BST)*(\d\d:\d\d)*)(?=[\s\.,T]|\Z)'
time = re.search(time_identifier, sentence, flags=re.U|re.I)
    if time:
        try:
            sentence = re.sub(time.groups()[0], '<time>%s</time>'%time.groups()[0], sentence, flags=re.U|re.I)
        except:
            sentence = re.sub(time.groups()[4], '<time>%s</time>'%time.groups()[4], sentence, flags=re.U|re.I)

对于上面提供的例子,我希望句子的输出是

<date>2004/12/01</date>T<time>09:38:27+01:00<time>
Wed, <date>2012/9/05</date> <time>10:55:17 UTC</time> %3C%3C%3C

但是re.sub方法并没有取代原句中的“09:38:27 + 01:00”

"<time>09:38:27+01:00</time>"

有人可以澄清一下这个原因吗?

2 个答案:

答案 0 :(得分:3)

你的表情过于复杂。以下是与完全相同的模式匹配的简化:

time_identifier = u'(?:(?<=[\s\.,T])|\A)(\d\d:\d\d(:\d\d)*[\s\.,+]*(UTC|GMT|CEST|EDT|IST|BST)*(\d\d:\d\d)*)(?=[\s\.,T]|\Z)'

由于前瞻断言((?=[\s\.,T]|\Z)部分),您的时间字符串未匹配;它限制匹配任何后跟空格,句号,逗号,字母T或字符串结尾的内容。您的第一个字符串紧跟在句子中的Wed后面;没有空格。

以下sentence匹配:

sentence = ('<date>2004/12/01</date>T09:38:27+01:00 '
            'Wed, <date>2012/9/05</date> 10:55:17 UTC %3C%3C%3C')

请注意时区后的额外空格。

答案 1 :(得分:1)

这里有几个问题。首先,你非常复杂的模式。其次,你不能做类似的事情:

re.sub('09:38:27+01', "<time>'09:38:27+01'</time>, s)

因为加号导致字符串s与模式不匹配(我假设您的组包含正确的时间),因此字符串的一部分将不会被标记。这回答了你的问题。

以下内容适用于您的示例数据(尽管我可能过度简化了初始模式):

p = '((?:\\d{2}:\\d{2}:\\d{2}\\+\\d{2}:\\d{2})|(?:\\d{2}:\\d{2}:\\d{2} UTC|GMT|CEST|EDT|IST|BST))'
result = re.findall(p, s)
print result
['09:38:27+01:00', '10:55:17 UTC']
r0 = result[0]
r0 = re.sub('\+', r'\+', r0)
s = re.sub(r0, "<time>%s</time>" % result[0], s)
s = re.sub(result[1], "<time>%s</time>" % result[1], s)
print s
'<date>2004/12/01</date>T<time>09:38:27+01:00</time>Wed, <date>2012/9/05</date> <time>10:55:17 UTC</time> %3C%3C%3C'

希望它有所帮助。