zoukankan      html  css  js  c++  java
  • 正则表达式 第四篇:贪婪和消耗字符

    转载:Python正则表达式之三:贪婪

    默认情况下,正则表达式进行贪婪匹配。所谓“贪婪”,是指当匹配到多种长度的字符串时,选择最长的;而非贪婪,就是在匹配多种长度的字符串时,选择最短的。

    默认情况下,正则表达在匹配字符时,会把字符消耗掉;可以使用环视结构来匹配位置,使得正则不消耗字符,即正则在匹配文本时,不消耗字符,只匹配位置。

    一,贪婪特性

    贪婪是正则表达式的默认属性,如下的几个例子都说明了正则表达式“贪婪”的特性:

    >>> re.findall('hi*', 'hiiiii')
    ['hiiiii']
    >>> re.findall('hi{2,}', 'hiiiii')
    ['hiiiii']
    >>> re.findall('hi{1,3}', 'hiiiii')
    ['hiii']

    二,非贪婪特性

    当我们期望正则表达式“非贪婪”地进行匹配时,需要通过语法明确说明:

    {2,5}?    捕获2-5次,但是选择次数最少的匹配

    在这里,问号?可能会有些让人犯晕,因为之前他已经有了自己的含义:前面的匹配出现0次或1次。其实,只要记住,当问号出现在表现不定次数的正则表达式之后时,就表示非贪婪匹配。

    正则表达式的非贪婪特性使用?来启动,非贪婪特性共有四种情况:

    • *?
    • +?
    • ??
    • {m,n}?

    还是上面的那几个例子,用非贪婪匹配,则结果如下:

    >>> re.findall('hi*?', 'hiiiii')
    ['h']
    >>> re.findall('hi{2,}?', 'hiiiii')
    ['hii']
    >>> re.findall('hi{1,3}?', 'hiiiii')
    ['hi']

    三,捕获和非贪婪

    在正则表达式匹配的过程中,其实存在“消耗字符”的过程,也就是说,一旦一个字符在匹配过程中被检索(消耗)过,后面的匹配就不会再检索这一字符了。

    (?=exp) 捕获,但不消耗字符,且匹配exp,返回位置
    (?!exp) 捕获,但不消耗字符,且不匹配exp,返回位置

    知道这个特性有什么用呢?还是用例子说明,比如,我们想找出字符串中出现过1次以上的单词:

    >>> sentence = "Oh what a day, what a lovely day!"
    >>> re.findall(r'(w+).*1', sentence)
    ['what']

    这样的正则表达式显然无法完成任务,为什么呢?原因就是,在第一个(w+)匹配到what,并且其后的1也匹配到第二个what的时候,“Oh what a day, what”这一段子串都已经被正则表达式消耗了,所以之后的匹配,将直接从第二个what之后开始。自然地,这里只能找出一个出现了两次的单词。

    那么解决方案,就和上面提到的(?=exp)语法相关了。这样的语法可以在分组匹配的同时,不消耗字符串!所以,正确的书写方式应该是:

    >>> re.findall(r'(w+)(?=.*1)', sentence)
    ['what', 'a', 'day']

    如果我们需要匹配一个至少包含两个不同字母的单词,则可以使用(?!exp)的语法:

    >>> re.search(r'([a-z]).*(?!1)[a-z]', 'aa', re.IGNORECASE)
    >>> re.search(r'([a-z]).*(?!1)[a-z]', 'ab', re.IGNORECASE)
    <_sre.SRE_Match object; span=(0, 2), match='ab'>

    参考文档:

    Python正则表达式之三:贪婪

  • 相关阅读:
    词汇表处理脚本
    jLowNote又,我为什么要说又,有bug
    于是按照贴吧某同学的指教,把imageViewer里那个愚蠢的语句改了
    捉到Bug一只,jLowNote里的
    高产赛母猪
    我超喜欢Nimbus风格的!
    专注写记事本三十年
    秒秒钟食言
    别再打了,Java和Python,你们其实都是C
    电话本写完了,发个1.0吧
  • 原文地址:https://www.cnblogs.com/ljhdo/p/11171996.html
Copyright © 2011-2022 走看看