匹配数字前面或后面没有数字的特定数字

时间:2017-04-04 18:03:28

标签: python regex regex-lookarounds

我有一个字符串:

string = u'11a2ee22b333c44d5e66e777e8888'

我想找到所有k个连续的数字块n <= k <= m

仅使用正则表达式: 比方说n=2m=3    使用(?:\D|^)(\d{2,3})(?:\D|$)

re.findall(u'(?:\D|^)(\d{2,3})(?:\D|$)',u'11a2ee22b333c44d5e66e777e8888')

给出这个输出:

['11', '333', '66']

期望的输出:

['11', '22', '333', '44', '66', '777']

我知道有其他解决方案,如:

filter(lambda x: re.match('^\d{2,3}$', x), re.split(u'\D',r'11a2ee22b333c44d5e66e777e8888'))

给出了所需的输出,但我想知道第一种方法有什么问题?

似乎re.findall按顺序排列并在匹配时跳过上一部分,那么可以做些什么呢?

3 个答案:

答案 0 :(得分:2)

注意:您在问题中显示的结果不是我得到的结果:

>>> import re
>>> re.findall(u'(?:\D|^)(\d{2,3})(?:\D|$)',u'11a2ee22b333c44d5e66e777e8888')
[u'11', u'22', u'44', u'66']

它仍然缺少你想要的一些比赛,但不是相同的。

问题在于,即使像(?:\D|^)(?:\D|$)这样的非捕获群体没有捕获他们匹配的内容,他们仍然消费 it。

这意味着产生'22'的匹配实际消耗了:

  1. e(?:\D|^) - 未捕获(但仍被消费)
  2. 22(\d{2,3}) - 已捕获
  3. b(?:\D|$) - 未捕获(但仍被消费)
  4. ...以便b之前无法再匹配333

    您可以通过lookbehind和lookahead语法获得所需的结果:

    >>> re.findall(u'(?<!\d)\d{2,3}(?!\d)',u'11a2ee22b333c44d5e66e777e8888')
    [u'11', u'22', u'333', u'44', u'66', u'777']
    

    在这里,(?<!\d)是一个负面的背后,检查匹配前面没有数字,(?!\d)是一个负前瞻,检查匹配后面没有数字。至关重要的是,这些结构不会消耗任何字符串。

    各种前瞻和后视构造在中描述 Python re文档的Regular Expression Syntax部分。

答案 1 :(得分:1)

环视正则表达式,\ d {2,3}表示2位或3位数,(?= [a-z])表示数字后面的字母。

In [136]: re.findall(r'(\d{2,3})(?=[a-z])',string)
Out[136]: ['11', '22', '333', '44', '66', '777']

答案 2 :(得分:1)

你甚至可以用一个函数来概括它:

afterrender: function() {
                Ext.fly('div').createChild({
                      tag: 'div',
                      html: "<label class='highlight'> Try the new <a href='#'>Beta version</a><span class='icon-clear'></span></label>"
                  }).on("click", function(e) {
                    if (e.target is <a>) {
                      //do some fun
                    }else if (e.target is <span>) {
                        //do some func
                   }
                }, this, { delegate: 'label' });  
        }