☰
python-字符串全解(六):正则表达式-预定义字符类
2026/9/27 17:58:15 网站建设 项目流程

上一章我们讲了字符类,这一章我们讲预定义字符类,预定义字符类就是正则表达式提前规定了特殊组合的字符,它代表的不是一个字符,而且一类字符,比如正数,字母等等。

3,预定义字符

预定义字符的形式有点像python的转义字符,包含了:数字(\d),非数字(\D),单词字符(\w),非单词字符(\W),空白(\s),非空白(\S)。从这些形式来看,小写和大写表示了相反的字符集合。这些集合其实都可以用上一节提到的字符类替代,但是这个更简洁,你必须记住这些都代表哪一个字符组合。

3.1数字(\d)

正则表达式用\d来来代表数字,用字符类表示就是[0-9],可以匹配从0到9的任意一个字符。我们简单的来看下面的例子。

import re a = "a1ca2cabc" a1 = "a\\dca2cabc" a2 = r"a\dca2cabc" # a3 = "a\dca2cabc" SyntaxWarning: invalid escape sequence '\d' b = re.findall(r'a\dc', a) c = re.findall(r'b[0-2]', a) d = re.findall(r'a\\dc', a1) e = re.findall('a\\\\dc', a1) f = re.findall(r'a\\dc', a2) g = re.findall('a\\\\dc', a2) print("a= {}, a1= {}, a2 = {}, b = {}, c = {}, d = {}, e = {}, f = {}, g = {}". format(a, a1, a2, b, c, d, e, f, g)) # 输出结果:a= a1ca2cabc, a1= a\dca2cabc, a2 = a\dca2cabc, b = ['a1c', 'a2c'], # c = [], d = ['a\\dc'], e = ['a\\dc'], f = ['a\\dc'], g = ['a\\dc']

b是通过\d代表数字,所以字符串中的a1c和a2c是符合正则的子串。c的效果是一样的,只是c用的是字符类,因为我们知道最大的数字是2,所以我们用了[0-2]而不是0-9,当然更为通用的写法是0-9,匹配所有数字。a1和a2的字符串是一样的,只是a1用\\转义代表\,所以a1和a2中的字符是\和d两个字符。这里必须在强调一下,python字符串中没有\d的转义,如果你前面不加r,直接写\d,会报不存在的转义字符的警告,所以我们需要写\\。a2是所有字符不转义,所以直接一个\就可以了。

d和e是正则表达式中如何匹配\d这两个字符,因为\d代表数字,所以需要将\写成\\,代表\只表示反斜杠本身,而不是预定义字符的开始。对于e,我们用了四个\\\\,这看起来有点晕。因为没有加r,所以\\\\表示两个\\本身,那么在正则表达式中两个反斜杠又表示\本身,而不是预定义字符。这就和d的效果是一样的。这和我们在转义和非转义章节提到的一样,首先正则表达式是一个字符串,需要遵循python字符串的语法,该转义的得先转义,转义之后的字符串然后再应用正则表达式的语法,明白了这一点,你就没那么困惑了。

f和g和d,e的正则表达式一样的,只是字符串用的是a2,a2只是不转义,所以和a1的串表示是一样的。

3.2非数字(\D)

只需要将d变成大写D,就表示了非数字。其对应的字符类是[^0-9]。我们简单看一个例子。

import re a = "a1ca2cabc" b = re.findall(r'a\Dc', a) c = re.findall(r'a[^0-9]c', a) print("a= {}, b = {}, c = {}". format(a, b, c)) # 输出结果:a= a1ca2cabc, b = ['abc'], c = ['abc']

b只是将上一节中的\d换成了\D,结果变成了abc,a和c中的是数字的子串没有得到匹配。c是同样的效果,只是用字符类的表示。

3.3单词字符(\w)

前面的章节我们学过\b表示单词边界,这个单词字符恰恰是相反的,表示字母,数字和下划线,对应的等价的字符类表示为[a-zA-Z0-9_],表示从小写字母a到z,大写字母A-Z,数字0到9以及下划线_。我看一下下面的代码:

import re a = "a1ca_cabca¥c" b = re.findall(r'a\wc', a) c = re.findall(r'a[a-zA-A0-9_]c', a) print("a= {}, b = {}, c = {}". format(a, b, c)) # 输出结果:a= a1ca_cabca¥c, b = ['a1c', 'a_c', 'abc'], # c = ['a1c', 'a_c', 'abc']

a中的子串有个a¥c,因为¥不属于\w,所以结果并没有a¥c。c是与b等价的字符类形式。同样,如果a字符串中如果有\w这两个字符,正则表达式匹配需要用r"\\w"或者"\\\\w",原因在3.1的小节中已经讨论了,这里不再赘述。

3.4非单词字符(\W)

和数字类型相似,只需要将w改成大写的W,就代表非单词字符,这恰恰和\b表示的单词边界是一致的,唯一的不同是,\b并不占位。对应的字符类的写法是[^a-zA-Z0-9_]:我们来看下下面的代码:

import re a = "a1ca_cabca¥c" b = re.findall(r'a\Wc', a) c = re.findall(r'a[^a-zA-A0-9_]c', a) d = re.findall(r'a\b.c', a) print("a= {}, b = {}, c = {}, d = {}". format(a, b, c, d)) # 输出结果:a= a1ca_cabca¥c, b = ['a¥c'], c = ['a¥c'], # d = ['a¥c']

b中我们将\w换成了\W,最后的结果变成了a¥c,这符合我们的预期。c是字符类的等价写法。d我们运用了\b加通配符.实现了同样的效果。这个例子印证了\b不是用来占位的,他只是告诉字符a之后的字符是单词的边界,那么根据单词边界的定义,后面字符不不能是字母,数字或下划线。我们用点号来匹配这个¥,后面跟c,达到了同样的效果。通过这个例子,我相信你对\b的用法会有更近一步的了解。

3.5空白(\s)

所谓空白,不单单的指空格,还包括了水平制表符(\t),垂直制表符(\v),换页(\f),换行(\n),回车(\r),其对应的字符类为[ \t\v\f\n\r],s在这里是space的意思,不能认为是字符串格式化表达式中的\s,注意这个集合里面有六个字符,第一个是空格。我们来看一些例子:

import re a = "|a\nca\tcabca¥ca c|" b = re.findall(r'a\sc', a) c = re.findall(r'a[ \t\v\f\r\n]c', a) print("a= {}, b = {}, c = {}". format(a, b, c)) # 输出结果:a= |a # ca cabca¥ca c|, b = ['a\nc', 'a\tc', 'a c'], # c = ['a\nc', 'a\tc', 'a c']

a字符串中包含了a\nc,a\tc以及a c(这个中间是空格),这三个都属于空白字符,所以被匹配,如b所示。c是等价的字符类表示方式。

3.6非空白(\S)

同样的,只需要将小写的s改成大写的S,就就可以表示相反的意思。对应字符类的表示为:

[^ \t\v\f\r\n]

我们看下面的代码:

import re a = "|a\nca\tcabca¥ca c|" b = re.findall(r'a\Sc', a) c = re.findall(r'a[^ \t\v\f\r\n]c', a) print("a= {}, b = {}, c = {}". format(a, b, c)) # 输出结果:a= |a # ca cabca¥ca c|, b = ['abc', 'a¥c'], # c = ['abc', 'a¥c']

从结果来看,abc和a¥c中间的字符都不是空白,所以这两个子串被匹配。

3.6字符类中嵌套预定义字符

从上面可以看出,用预定义字符可以比用字符类更简洁。假如我们既想匹配数字,又想匹配空白字符呢?上一节我们讲了字符类,在字符类中也可以嵌套预定义字符,我们把\d和\s一起放入中括号中,就像使用普通字符那样,就可以达到同时匹配数字和空白字符的效果。如下代码所示:

import re a = "|a\nca\tca1ca¥ca c|" b = re.findall(r'a[\s\d]c', a) c = re.findall(r'a[0-9 \t\v\f\r\n]c', a) print("a= {}, b = {}, c = {}". format(a, b, c)) # 输出结果:a= |a # ca ca1ca¥ca c|, b = ['a\nc', 'a\tc', 'a1c', 'a c'], # c = ['a\nc', 'a\tc', 'a1c', 'a c']

b匹配了a和c之间是数字或者空白的子串,c用非预定义字符表示。同样,如果需要表示非数字和空白,只需要加上^就可以。如下所示:

import re a = "|a\nca\tca1ca¥ca c|" b = re.findall(r'a[^\s\d]c', a) c = re.findall(r'a[^0-9 \t\v\f\r\n]c', a) print("a= {}, b = {}, c = {}". format(a, b, c)) # 输出结果:a= |a # ca ca1ca¥ca c|, b = ['a¥c'], c = ['a¥c']

字符串a中字符a和c之间不是数字的子串只有a¥c符合。

讲到这里,预定义字符我们就讲完了。上面代码,我们都没涉及到字符出现两次或者多次的时候,假如有一个字符串“a112345678ca123c,我们想匹配中间是多个不确定长度的数字,我们现在所学的就无能为力了。这就引出下一章我们要讲的内容,量词,通过两次我们可以表示各种重复的场景,从而解决重复字符的问题。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询