正则表达式指南
摘要:本文档是关于如何在Python中使用正则表达式进行字符串匹配的入门教程。它提供了比Python官方文档更易于理解的内容。
正则表达式(Regular Expressions,简称REs、regexs或regex patterns)是一种内嵌在Python中的微小且高度专业化的编程语言。通过使用这种小型语言,您可以编写规则来匹配可能的字符串,例如英文句子、电子邮件地址、TeX命令等。然后,您可以提出诸如“此字符串是否与表达式匹配?”、“字符串中是否存在表达式的匹配项?”等问题。此外,您还可以使用正则表达式来修改字符串,或以各种方式将其拆分。
正则表达式会被编译成一系列字节码,然后由C语言编写的匹配引擎执行。对于高级用途,可能有必要特别注意引擎将如何执行一个给定的正则,并以某种方式编写正则,以生成运行更快的字节码。本文不涉及优化问题,因为这要求您对正则引擎的匹配过程有很好的了解。
正则表达式语言相对较小且受限,因此并非所有可能的字符串处理任务都可以使用正则表达式完成。有些任务尽管可以用正则表达式来完成,但表达式会变得非常复杂。这些情况下,最好通过编写Python代码来进行处理。也许Python代码会比精心设计的正则表达式慢,但它可能更容易理解。
让我们从最简单的正则表达式开始吧。由于正则表达式是用来操作字符串的,我们将从最常见的任务开始:匹配字符。关于正则表达式背后的计算机科学的详细解释(确定性和非确定性有限自动机),你可以参考几乎所有关于编写编译器的教科书。
大多数字母和符号都会简单地匹配自身。例如,正则表达式test将会精确地匹配到test。(你可以启用不区分大小写模式,让这个正则也匹配Test或TEST,稍后会详细介绍。)
但该规则有例外。有些字符是特殊的元字符(metacharacters),并不匹配自身。事实上,它们表示匹配一些非常规的内容,或者通过重复它们或改变它们的含义来影响正则的其他部分。本文的大部分内容都致力于讨论各种元字符及其作用。
这是元字符的完整列表。它们的含义将在本HOWTO的其余部分进行讨论。
首先介绍的元字符是[和]。这两个元字符用于指定一个字符类,也就是你希望匹配的字符的一个集合。这些字符可以单独地列出,也可以用字符范围来表示(给出两个字符并用'-'分隔)。例如,[abc]将匹配a、b、c之中的任意一个字符;这与[a-c]相同,后者使用一个范围来表达相同的字符集合。如果只想匹配小写字母,则正则表达式将是[a-z]。
元字符(除了\)在字符类中是不起作用的。例如,[akm';'$'通常是一个元字符,但在一个字符类中它的特殊性被消除了。
你可以通过对集合取反来匹配字符类中未列出的字符。方法是把^放在字符类的最开头。例如,[^5]将匹配除'5'之外的任何字符。如果插入符出现在字符类的其他位置,则它没有特殊含义。例如:[5^]将匹配'5'或'^'。
也许最重要的元字符是反斜杠,\。与Python字符串字面量一样,反斜杠后面可以跟各种字符来表示各种特殊序列。它还用于转义元字符,以便可以在表达式中匹配元字符本身。例如,如果需要匹配一个[或\,可以在其前面加上一个反斜杠来消除它们的特殊含义:[或\。
一些以''开头的特殊序列表示预定义的字符集合,这些字符集通常很有用,例如数字集合、字母集合或非空白字符集合。
让我们举一个例子:\w匹配任何字母数字字符。如果正则表达式以bytes类型表示,\w相当于字符类[a-zA-Z0-9_]。如果正则表达式是str类型,\w将匹配由unicodedata模块提供的Unicode数据库中标记为字母的所有字符。通过在编译正则表达式时提供re.ASCII标志,可以在str表达式中使用较为狭窄的\w定义。
正则表达式指南
以下为特殊序列的不完全列表。有关Unicode字符串正则表达式的序列和扩展类定义的完整列表,参见标准库参考中正则表达式语法的最后一部分。通常,Unicode版本的字符类会匹配Unicode数据库的相应类别中的任何字符。
这些序列可以包含在字符类中。例如,[\s,.]是一个匹配任何空白字符、','或'.'的字符类。
本节的最后一个元字符是.。它匹配除换行符之外的任何字符,并且有一个可选模式(re.DOTALL),在该模式下它甚至可以匹配换行符。.通常用于你想匹配“任何字符”的场景。
能够匹配各种各样的字符集合是正则表达式可以做到的第一件事,而这是字符串方法所不能做到的。但是,如果正则表达式就只有这么一个附加功能,它很难说的上有多大优势。另一个功能是,你可以指定正则的某部分必须重复一定的次数。
我们先来说说重复元字符*。*并不是匹配一个字面字符'*'。实际上,它指定前一个字符可以匹配零次或更多次,而不是只匹配一次。
例如,ca*t将匹配ct(0个a)、cat(1个a)、caaat(3个a)等等。
类似*这样的重复是贪婪的。当重复正则时,匹配引擎将尝试重复尽可能多的次数。如果表达式的后续部分不匹配,则匹配引擎将回退并以较少的重复次数再次尝试。
通过一个逐步示例更容易理解这一点。让我们分析一下表达式a[bcd]*b。该表达式首先匹配一个字母a,接着匹配字符类[bcd]中的零个或更多个字母,最后以一个b结尾。现在想象一下用这个正则来匹配字符串abcbd。
步骤1:a匹配成功。
步骤2:引擎尽可能多地匹配[bcd]*,直至字符串末尾。
步骤3:引擎尝试匹配b,但是当前位置位于字符串末尾,所以匹配失败。
步骤4:回退,让[bcd]*少匹配一个字符。
步骤5:再次尝试匹配b,但是当前位置上的字符是最后一个字符d。
步骤6:再次回退,让[bcd]*只匹配bc。
步骤7:再次尝试匹配b。这一次当前位置的字符是b,所以它成功了。
此时正则表达式已经到达了尽头,并且匹配到了abcb。这个例子演示了匹配引擎一开始会尽其所能地进行匹配,如果没有找到匹配,它将逐步回退并重试正则的剩余部分,如此往复,直至[bcd]*只匹配零次。如果随后的匹配还是失败了,那么引擎会宣告整个正则表达式与字符串匹配失败。
另一个重复元字符是 ,表示匹配一次或更多次。请注意*与 之间的差别。*表示匹配零次或更多次,也就是说它所重复的内容是可以完全不出现的。而 则要求至少出现一次。举一个类似的例子,ca t可以匹配cat(1个a)或caaat(3个a),但不能匹配ct。
此外还有两个重复操作符或限定符。问号?表示匹配一次或零次;你可以认为它把某项内容变成了可选的。例如,home-?brew可以匹配homebrew或home-brew。
最复杂的限定符是{m,n},其中m和n都是十进制整数。该限定符表示必须至少重复m次,至多重复n次。例如,a/{1,3}b将匹配ab、a//b和a///b。它不能匹配ab,因为其中没有斜杠,也不能匹配a////b,因为其中有四个斜杠。
m和n不是必填的,缺失的情况下会设定为默认值。缺失m会解释为最少重复0次,缺失n则解释为最多重复无限次。
最简单情况{m}将与前一项完全匹配m次。例如,a/{2}b将只匹配a//b。
细心的读者可能会注意到另外三个限定符都可以使用此标记法来表示。{0,}等同于*,{1,}等同于 ,而{0,1}等同于?。在可能的情况下使用*、 或?会更好,因为它们更为简短易读。
现在我们已经了解了一些简单的正则表达式,那么我们如何在Python中实际使用它们呢?re模块提供了正则表达式引擎的接口,可以让你将正则编译为对象,然后用它们来进行匹配。
正则表达式被编译成模式对象,模式对象具有各种操作的方法,例如搜索模式匹配或执行字符串替换。
正则表达式被编译成模式对象,模式对象具有各种操作的方法,例如搜索模式匹配或执行字符串替换。
正则表达式被编译成模式对象,模式对象具有各种操作的方法,例如搜索模式匹配或执行字符串替换。
正则表达式被编译成模式对象,模式对象具有各种操作的方法,例如搜索模式匹配或执行
本文主题词:正则表达式示例,正则表达式实战,正则表达?,正则表达式入门,正则表达式必知必会,正则表达式^用法,正则表达式经典实例,正则表达式知乎,正则表达式详解,最全正则表达式