小白快快跑哦头像
关注
python-字符串全解(六):正则表达式-字符类封面图

python-字符串全解(六):正则表达式-字符类

上一章我们讨论了字面字符,这一章我们讨论字符类。字符类我们可以理解为一个字符集合。上一章讲的字面字符,我们可以排列字符去匹配,例如匹配表达式为r"abc",我们可以在字符串中查找abc子串,但是如果我想要字符串中查找可能是a开头,可能是b开头,可能是c开头的子串呢?例如我要查找abc,bbc,cbc呢?如果按照上一章我们学到的知识,可能我们得写三个正则表达式去匹配,这样未免太复杂。如果我们需要用一个正则表达式同时获取这三种形式的匹配呢?这就用到了字符类(当然学到后面,我们还有别的方式)。

2,字符类

字符类包含了:通配符(.),集合中的任意一个字符([abc]),除了集合中的任意字符([^abc]),集合中开始到结束范围内的任意一个字符([a-z]),多个范围内的任意一个字符([a-z0-9])。

我们可以看到,除了通配符,其他的都包含在方括号中[],接下来我们来分别介绍。

2.1通配符(.)

这个点号是通配符,可以用来匹配任意的字符,除了换行符。至于为什么不能匹配换行符,这里面有正则表达式本身语法的设计,目前我们先不谈这个问题,只需要记住几可以了。我可以看看点号的例子。

import re
a = "abc\nadc"
b = re.findall(r'a.c', a)
b1 = re.findall(r'abc.a', a)
print("b = {}, b1 = {}".format(b, b1))
# 输出结果:b = ['abc', 'adc'], b1 = []

b用通配符最终匹配了abc和adc这两个子串,说明.号可以匹配任意字符,但是b1的结果是空,说明.不能匹配换行符。

2.2集合中的任意一个字符([abc])

上面说的点号的匹配范围太过于宽泛,如果我只想匹配固定范围内任意一个字符,这时候用这个语法就再合适不过了。这个语法是中括号中,写入我们想要匹配的字符集合,要注意,这个中括号中字符只能匹配一个字符,也就是说只要任何一个字符在中括中能找到,就算匹配成功,这个中括号的字符匹配就结束了。看下面的代码:

import re
a = "abc\naac\naec"
b = re.findall(r'a.c', a)
c = re.findall(r'a[abc]c', a)
print("b = {}, c = {}".format(b, c))
# 输出结果:b = ['abc', 'aac', 'aec'], c = ['abc', 'aac']

b我们用的是通配符,所以得到了三个结果,c我们用了a[abc]c,表明a和c之间的字符必须是abc这三个字符中的一个,所以匹配了abc,aac,但是因为e不在[abc]这样的集合中,所以aec没有被匹配。

2.3除了集合中的任意字符([^abc])

刚才我们用集合[abc]表示需要是集合中的任意一个字符,但是如果我们匹配的字符需要不是集合中的字符的话,就需要在[]中的第一个位置加上^,来得到相反的效果,表明接下来的字符不能是这个集合中的字符。看下面的代码:

import re
a = "abc\naac\naec"
b = re.findall(r'a[abc]c', a)
c = re.findall(r'a[^abc]c', a)
print("b = {}, c = {}".format(b, c))
# 输出结果:b = ['abc', 'aac'], c = ['aec']

我们可以看到b和c得到了相反的结果。其中b中则正则表达式要求a和c之间的字符是a,b,c其中一个,所以得到了abc和aac,而c的正则表示要求a和c之间的字符不能是a,b,c其中的一个,所以得到了结果是aec。

2.4集合中开始到结束范围内的任意一个字符([a-z])

如果一个字符集包含的字符比较多,并且这些字符的码点值是连续的(不了解码点值,可以参照我之前的关于字符串的文章),这时候我们就可以用范围来表示,上一小节我们的正则表达式是r"abc",此时我们可以写成r"a[a-c]c",当然本来这个字符集就只有三个,这样修改后其实也没什么要多的意义,我们看一个比较多的例子。

import re
a = "abcazczqcssqqarcazcaac"
b = re.findall(r'a[abcdefghijklmnopqrstuvwxyz]c', a)
c = re.findall(r'a[a-z]c', a)
print("b = {}, c = {}".format(b, c))
# 输出结果:b = ['abc', 'azc', 'arc', 'azc', 'aac'], 
c = ['abc', 'azc', 'arc', 'azc', 'aac']

上面代码中b中的正则和c中的正则是等效的,但是c却简洁很多。如果取在一个连续的范围之内,就可以用这种形式,这个区间左右字符都是包含的,我们从c的结果中有aac和azc就可以证明这一点。

2.5多个范围内的任意一个字符([a-z0-9])。

这一小节是上面的一个扩展,我们可以在一个[]写多个范围,我们看下面的代码:

import re
a = "abcazczqcarcazcaaca3ca5ca9c"
b = re.findall(r'a[a-z1-59]c', a)
print("b = {}".format(b))
# 输出结果:b = ['abc', 'azc', 'arc', 'azc', 'aac', 'a3c', 'a5c', 'a9c']

b这表达式包含了两个范围a-z和1-5,然后我们注意后面还有一个9,9是一个单独的字符,千万不能理解成1-59,在[]中都是单个字符,所以不会存在59这样的字符。从结果中我们也可以看出a9c确实匹配了9,a3c和a5c则是匹配了1-5的范围。

2.6匹配[或者]等元字符

因为本章我们介绍的语法大多都是包含了[],所以很自然而然的涉及到一个问题,如何匹配“[”或者“]”本身?其实这关系到了正则表达式的保留字符,不止有[],我们还学到了\,以及点号‘.’,我们也称之为元字符,后面我们还会学到更多,目前我们遇到的就是这四个。为了匹配这些元字符,我们需要在这些字符前面加反斜杠,以保证这写字符不会被正则表达式的规则解析,而只代表字符本身的含义。我们看一些例子:

import re
a = "a\\nb[a]a.c"
b = re.findall(r'a\\n', a)
c = re.findall(r'b\[a\]a', a)
d = re.findall(r'a\.c', a)
e = re.findall(r'b.a]a', a)
f = re.findall(r'b[a]a', a)
print("a= {}, b = {}, c = {}, d = {}, e = {}, f = {}".
      format(a, b, c, d, e, f))
# 输出结果:a= a\nb[a]a.c, b = ['a\\n'], c = ['b[a]a'], 
# d = ['a.c'], e = ['b[a]a'], f = []

我们先看a这个字符串,其中\\n是两个字符,并不是换行,从a的打印结果也可以看出是两个字符。我们用\\代表\本身。可以看到b我们用\\来表示\本身,最后结果匹配到了。同样c我们用\[来代表[本身,用\]来代表]本身。d也是一样的,用\.来代表‘.’。 e我们用了通配符,并且我们还用了一个],为什么这个正则表达式中]可以代表自己,而需要加\前缀呢?原因是因为这个右中括号]出现之前,并没有左中括号[,所以正则表达式会将这个右中括号]当成是其本身,而不是元字符。f不会匹配到对应的子串,因为先出现了左中括号,这时候正则表达式会寻找配对的左括号],并当作是一个集合,这个集合里只有一个字符a,所以f的正则表达式等价于r'baa',a中不包含这样的子串,所以结果为空。

到这里我们就学习完了字符类,其实字符类中还可以放入预定义类,因为预定义字符我们还没有讲到,下一章我们预定义字符的时候,我们再来看字符类中放预定义字符的例子。

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/ttug22/article/details/166590779

文章来源转载

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--