• Python中的正则表达式


    在了解了关于正则表达式的全部知识后,开始查看 Python 当前如何通过使用 re 模块来支持正则表达式,re 模块在古老的 Python 1.5 版中引入,用于替换那些已过时的 regex 模块和 regsub 模块——这两个模块在 Python 2.5 版中移除,而且此后导入这两个模块中的任意一个都会触发 ImportError 异常。re 模块支持更强大而且更通用的 Perl 风格(Perl 5 风格)的正则表达式,该模块允许多个线程共享同一个已编译的正则表达式对象,也支持命名子组。

    表 1-2 列出了来自 re 模块的更多常见函数和方法。 它们中的大多数函数也与已经编译的正则表达式对象(regex object)和正则匹配对象(regex match object)的方法同名并且具有相同的功能。本节将介绍两个主要的函数/方法——match()和 search(),以及 compile()函数。下一节将介绍更多的函数,但如果想进一步了解将要介绍或者没有介绍的更多相关信息,请查阅 Python 的相关文档。

     

    核心提示:编译正则表达式(编译还是不编译?)

    在 Core Python Programming 或者即将出版的 Core Python Language Fundamentals 的执行环境章节中,介绍了 Python 代码最终如何被编译成字节码,然后在解释器上执行。特别是,我们指定 eval()或者 exec(在 2.x 版本中或者在 3.x 版本的 exec()中)调用一个代码对象而不是一个字符串,性能上会有明显提升。这是由于对于前者而言,编译过程不会重复执行。换句话说,使用预编译的代码对象比直接使用字符串要快,因为解释器在执行字符串形式的代码前都必须把字符串编译成代码对象。

    同样的概念也适用于正则表达式—在模式匹配发生之前,正则表达式模式必须编译成正则表达式对象。由于正则表达式在执行过程中将进行多次比较操作,因此强烈建议使用预编译。而且,既然正则表达式的编译是必需的,那么使用预编译来提升执行性能无疑是明智之举。 re.compile()能够提供此功能。

    其实模块函数会对已编译的对象进行缓存,所以不是所有使用相同正则表达式模式的 search()和 match()都需要编译。即使这样,你也节省了缓存查询时间,并且不必对于相同的字符串反复进行函数调用。在不同的 Python 版本中,缓存中已编译过的正则表达式对象的数目可能不同,而且没有文档记录。 purge()函数能够用于清除这些缓存。

     

    1.使用compile()函数编译正则表达式

     

    那么如何使用compile()函数编译正则表达式呢?

    后续将扼要介绍的几乎所有的 re 模块函数都可以作为 regex 对象的方法。注意,尽管推荐预编译,但它并不是必需的。如果需要编译,就使用编译过的方法;如果不需要编译,就使用函数。幸运的是,不管使用函数还是方法,它们的名字都是相同的(也许你曾对此感到好奇,这就是模块函数和方法的名字相同的原因,例如, search()、 match()等)。因为这在大多数示例中省去一个小步骤,所以我们将使用字符串替代。我们仍将会遇到几个预编译代码的对象,这样就可以知道它的过程是怎么回事。

    对于一些特别的正则表达式编译,可选的标记可能以参数的形式给出,这些标记允许不区分大小写的匹配,使用系统的本地化设置来匹配字母数字,等等。请参考表 1-2 中的条目以及在正式的官方文档中查询关于这些标记(re.IGNORECASE、 re.MULTILINE、 re.DOTALL、e.VERBOSE 等) 的更多信息。 它们可以通过按位或操作符(|)合并。

    这些标记也可以作为参数适用于大多数 re 模块函数。如果想要在方法中使用这些标记, 它们必须已经集成到已编译的正则表达式对象之中,或者需要使用直接嵌入到正则表达式本身的(? F)标记,其中 F 是一个或者多个 i(用于 re.I/IGNORECASE)、 m(用于 re.M/MULTILINE)、14 第 1 部分 通用应用主题s(用于 re.S/DOTALL) 等。如果想要同时使用多个,就把它们放在一起而不是使用按位或操作,例如,(?im) 可以用于同时表示 re.IGNORECASE 和 re.MULTILINE。

     

    2.匹配对象以及group()和groups()方法

     

    当处理正则表达式时,除了正则表达式对象之外,还有另一个对象类型:匹配对象。这些是成功调用 match()或者 search()返回的对象。匹配对象有两个主要的方法: group()和groups()。

    group()要么返回整个匹配对象,要么根据要求返回特定子组。 groups()则仅返回一个包含唯一或者全部子组的元组。如果没有子组的要求,那么当group()仍然返回整个匹配时,groups()返回一个空元组。

    除此之外,Python 正则表达式也允许命名匹配,这里就不再赘述,有兴趣的话可以查阅完整的re模块文档以获取详细内容。

    3.使用match()方法匹配字符串

     

    match()是将要介绍的第一个 re 模块函数和正则表达式对象(regex object)方法。match()函数试图从字符串的起始部分对模式进行匹配。如果匹配成功,就返回一个匹配对象; 如果匹配失败,就返回 None,匹配对象的 group()方法能够用于显示那个成功的匹配。下面是如何运用 match()(以及 group())的一个示例:

     

    因为上面的匹配失败,所以 m 被赋值为 None,而且以此方法构建的 if 语句没有指明任何操作。对于剩余的示例,如果可以,为了简洁起见,将省去 if 语句块,但在实际操作中,最好不要省去以避免 AttributeError 异常(None 是返回的错误值,该值并没有 group()属性[方法])。

    此外,只要模式从字符串的起始部分开始匹配,即使字符串比模式长,匹配也仍然能够成功。例如,模式“foo”将在字符串“food on the table”中找到一个匹配,因为它是从字符串的起始部分进行匹配的。

     

    可以看到,尽管字符串比模式要长,但从字符串的起始部分开始匹配就会成功。子串“foo”是从那个比较长的字符串中抽取出来的匹配部分。

    甚至可以充分利用 Python 原生的面向对象特性,忽略保存中间过程产生的结果。但是如果匹配失败将会跑出AttributeError异常,如下面实例。

     

     

    4.使用search()在一个字符创中查找模式(搜索与匹配的对比)

     

    其实,想要搜索的模式出现在一个字符串中间部分的概率,远大于出现在字符串起始部分的概率。这也就是 search()派上用场的时候了。 search()的工作方式与 match()完全一致,不同之处在于 search()会用它的字符串参数,在任意位置对给定正则表达式模式搜索第一次出现的匹配情况。如果搜索到成功的匹配,就会返回一个匹配对象; 否则, 返回 None。

    我们将再次举例说明 match()和 search()之间的差别。 以匹配一个更长的字符串为例,这次使用字符串“foo”去匹配“seafood”:

     

    可以看到,此处匹配失败。 match()试图从字符串的起始部分开始匹配模式;也就是说,模式中的“f”将匹配到字符串的首字母“s”上,这样的匹配肯定是失败的。然而,字符串“foo”确实出现在“seafood”之中(某个位置),所以,我们该如何让 Python 得出肯定的结果呢?答案是使用 search()函数,而不是尝试匹配。 search()函数不但会搜索模式在字符串中第一次出现的位置,而且严格地对字符串从左到右搜索。

     

    注:此处搜索成功,但匹配失败

    此外, match()和 search()都使用1节中介绍的可选的标记参数。最后,需要注意的是,等价的正则表达式对象方法使用可选的 pos 和 endpos 参数来指定目标字符串的搜索范围。

    本节后面将使用 match()和 search()正则表达式对象方法以及 group()和 groups()匹配对象方法,通过展示大量的实例来说明 Python 中正则表达式的使用方法。我们将使用正则表达式语法中几乎全部的特殊字符和符号。

    5.匹配多个字符串

    上一篇随笔中在正则表达式中使用了择一匹配(|)符号,如下为在Python中使用正则表达式的方法。

     

    6.匹配任何单个字符

    在后续的示例中,我们展示了点号(.)不能匹配一个换行符 或者非字符,也就是说,一个空字符串。

    注:部分内容来源为Python核心编程(第3版),[美] Wesley Chun 著
    孙波翔 李斌 李晗 译 ,人民邮电出版社

     

  • 相关阅读:
    PHP实现发送模板消息(微信公众号版)
    laravel 跨域问题
    微信授权登录
    支付demo2
    支付demo1
    微信支付注意点
    微信支付方式区分
    debian,dietpi,linux中文乱码解决方法
    嵌入式应该深入专研STM32还是继续学习linux内核驱动呢?
    arduino下载ESP8266开发板的方法
  • 原文地址:https://www.cnblogs.com/z1174299705/p/8395044.html
Copyright © 2020-2023  润新知