【问题标题】:re.sub in python do not always substitute the stringpython中的re.sub并不总是替换字符串
【发布时间】:2012-10-19 14:48:01
【问题描述】:

当我尝试用另一个字符串替换一个字符串时,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>"

谁能说明原因?

【问题讨论】:

  • 如果你打印time.groups()[0],你会看到你的正则表达式没有抓取09:38:27+01:00。我不知道为什么(而且我不打算尝试对那个可怕的问题进行分类并弄清楚)。
  • 我没有时间研究你的问题,但我强烈推荐regex101.com 来设计你的表达方式,应该会有所帮助。
  • 你真的想简化那个表达式; [:]{1} 只是表达: 的一种非常冗长的方式;例如完全匹配一个冒号。同样,无需将\d 括在括号中([\d]\d 相同)。而\d\d\d{2} 略短。
  • @Martijn:我在构建正则表达式时考虑了许多其他日期格式。我一定会改变它们
  • @mgilson:在我的电脑上测试,正则表达式捕获 09:38:27+01:00,但没有标记

标签: python regex python-2.7


【解决方案1】:

你的表达方式非常复杂。以下是匹配完全相同模式的简化:

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

注意时区后面的多余空格。

【讨论】:

    【解决方案2】:

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

    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'
    

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 2014-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-26
      • 1970-01-01
      • 1970-01-01
      • 2021-12-02
      相关资源
      最近更新 更多