【问题标题】:Python: Unexpected regex behaviour for {n} matchPython:{n} 匹配的意外正则表达式行为
【发布时间】:2015-02-10 15:36:44
【问题描述】:

我在http://regexpal.com/ 上测试了以下代码,它与我想要的字符串正确匹配。我想找到出现在 4 块中的 16 位数字,中间有一个空格,所以我写了以下正则表达式:

\d{4}(\s\d{4}){3}

即匹配 4 个数字,然后匹配三个重复的空格组,后跟四个数字。在正则表达式上,这正确匹配:

test1234 消息1234 5678 1234 5678

然而,在 Python 中,我运行以下代码:

>>> import re
>>> p = re.compile('\d{4}(\s\d{4}){3}')
>>> p.findall('test1234 message1234 5678 1234 5678')
[' 5678']
>>>

我不明白为什么它与“5678”的第二个实例匹配,以及为什么它与我预期的数字块不匹配。

【问题讨论】:

    标签: python regex


    【解决方案1】:

    原始字符串是定义正则表达式的推荐方式,但这里的问题主要是因为findall方法的实现。您需要将正则表达式中的捕获组转换为非捕获组。因为re.findall 函数优先考虑捕获,然后是匹配项。您的正则表达式 \d{4}(\s\d{4}){3} 匹配 16 位数字,但仅捕获最后四个加上前面的空格。

    p = re.compile(r'\d{4}(?:\s\d{4}){3}')
    

    示例:

    >>> import re
    >>> p = re.compile(r'\d{4}(\s\d{4}){3}')
    >>> p.findall('test1234 message1234 5678 1234 5678')
    [' 5678']
    >>> p = re.compile(r'\d{4}(?:\s\d{4}){3}')
    >>> p.findall('test1234 message1234 5678 1234 5678')
    ['1234 5678 1234 5678']
    

    【讨论】:

    • 我认为你应该提到原始字符串是推荐的正则表达式编写方式,但在这种情况下,问题来自findall的实现,如果有则切换到使用来自捕获组的内容任何在正则表达式中。
    【解决方案2】:

    您需要在字符串前面加上 r 或转义反斜杠:

    p = re.compile(r'\d{4}(\s\d{4}){3}')
    

    p = re.compile('\\d{4}(\\s\\d{4}){3}')
    

    【讨论】:

    • 原始字符串不是这里的问题,尽管这是推荐的做法。 Python 为无法识别的转义序列保留 \
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多