正则表达式中字符主要分为两类,一类是普通字符,一类是特殊字符。
普通字符举例:
下面是一串阿里云服务器所在地域,城市,region id,和可用区数量的对照关系
华北 1 青岛 cn-qingdao 2
华北 2 北京 cn-beijing 8
华北 3 张家口 cn-zhangjiakou 3
华北 5 呼和浩特 cn-huhehaote 2
华北 6 乌兰察布 cn-wulanchabu 2
华东 1 杭州 cn-hangzhou 8
华东 2 上海 cn-shanghai 7
华南 1 深圳 cn-shenzhen 5
华南 2 河源 cn-heyuan 2
华南 3 广州 cn-guangzhou 2
西南 1 成都 cn-chengdu 2
假如我们要找到所有华北的服务器,那么我们可以直接使用“华北”这个关键字来找到符合的选项,如下图:
这里华北就是一个普通字符,类似的例如普通英文字母也是一个普通字符。而特殊字符指的是这些字符不是用来匹配原来文本中的内容(很多情况下这些特殊字符在原来文本中就不会出现)。这些特殊字符是为了特殊的用法来实现的,分别有不同的含义。下面就是这些特殊字符,我们来一个一个学习用法.
. * + ? \ [ ] ^ $ { } | ( )
. 表示要匹配除了 换行符 之外的任何 单个 字符。
例如我们要在之前阿里云服务器地点那个例子中找出所有服务器所在地域有“南”字的,观察得知有华南,也有西南。这时候简单的方法就是搜索“.南”
点号放在前面后面都一样,甚至可以多加几个,例如我们要找到所有华北地区的服务器,注意格式是“华北”+“空格”+“数字”,那么就可以用两个点号来代替两个字符,如下
在python代码中,就可以用过re来提取相关的内容,首先import re(re是正则表达式的库),定义正则表达式,然后用一个for循环,输出所有符合条件的内容。注意p=re.compile(r’.南’)中的r是禁止python本身对正则表达式的内容进行转义(因为某些特殊字符在python中有特殊含义,会被python识别陈别的指令,加入r的意思就是我不需要转义,直接就按照用户定义的原始字符去搜)
content='''
华北 1 青岛 cn-qingdao 2
华北 2 北京 cn-beijing 8
华北 3 张家口 cn-zhangjiakou 3
华北 5 呼和浩特 cn-huhehaote 2
华北 6 乌兰察布 cn-wulanchabu 2
华东 1 杭州 cn-hangzhou 8
华东 2 上海 cn-shanghai 7
华南 1 深圳 cn-shenzhen 5
华南 2 河源 cn-heyuan 2
华南 3 广州 cn-guangzhou 2
西南 1 成都 cn-chengdu 2
'''
import re
p = re.compile(r'.南')
for one in p.findall(content):
print(one)
- 表示匹配前面的子表达式任意次,包括0次。
例如在我们的例子中选择所有地域中有1的服务器信息,那么这时候正则表达式就是1.*
如何理解呢?首先1是我们需要匹配的第一个字符,接着是点号,点号表示任意字符,然后星号就表示这之后所有的字符(就是符合1.这个表达式的任意次)。假如不输入星号,只输入1. 那么结果如下:
放到pycharm(或者vs code)中试试,代码如下
content='''
华北 1 青岛 cn-qingdao 2
华北 2 北京 cn-beijing 8
华北 3 张家口 cn-zhangjiakou 3
华北 5 呼和浩特 cn-huhehaote 2
华北 6 乌兰察布 cn-wulanchabu 2
华东 1 杭州 cn-hangzhou 8
华东 2 上海 cn-shanghai 7
华南 1 深圳 cn-shenzhen 5
华南 2 河源 cn-heyuan 2
华南 3 广州 cn-guangzhou 2
西南 1 成都 cn-chengdu 2
'''
import re
p = re.compile(r'1.*')
for one in p.findall(content):
print(one)
- 表示匹配前面的子表达式一次或多次,不包括0次。
加号和星号的区别在于加号不包括0次,而星号包括0次
这次我们例子换一下,以下字符:
华北 1青岛cn-qingdao2
华北 2北京cn-beijing8
华北 3张家口cn-zhangjiakou3
华北 5呼和浩特cn-huhehaote2
华北 6乌兰察布cn-wulanchabu2
华东 1杭州cn-hangzhou8
华东 2上海cn-shanghai7
华南 1
华南 2河源cn-heyuan2
华南 3广州cn-guangzhou2
西南 1成都cn-chengdu2
我们选出所有区域名字带1的后面的内容,如果后面的信息是缺失的是空的,我们就不选。如果使用1.* 结果如下
我们发现“华南1”后面没有数据,不是我们想选取的内容,但是还是被选取了进来。因为*表示符合前面的子表达式任意次数(包括0次),“华南1”后面没有符合要求的,因此是0次,还是会被选中。这时候就需要使用加号,因为加号排除了0次,直接找至少一次符合条件的。因为“华南1”后面没有任何字符,因此就不会被选中了. 如下,使用1.+就可以排除掉“华南1”。
? 表示匹配前面的子表达式0次或1次。
沿用加号的例子,这里1.?表示也会把“华南1”选上,为啥呢?因为“华南1”之后没有任何字符,因此匹配问号前面的子表达式“1.”的次数为0次,因此还是会被选择上
假如我们有这样一串字符,
‘<华北 1青岛cn-qingdao2><华北 2北京cn-beijing8><华北 3张家口cn-zhangjiakou3><华北
5呼和浩特cn-huhehaote2><华北 6乌兰察布cn-wulanchabu2><华东 1杭州cn-hangzhou8><华东
2上海cn-shanghai7><华南 1><华南 2河源cn-heyuan2><华南 3广州cn-guangzhou2><西南
1成都cn-chengdu2>’
我们想提取之后变成变成这样,即每个尖括号里面的内容都被单独提取出来
<华北 1青岛cn-qingdao2>
<华北 2北京cn-beijing8>
<华北 3张家口cn-zhangjiakou3>
<华北 5呼和浩特cn-huhehaote2>
<华北 6乌兰察布cn-wulanchabu2>
<华东 1杭州cn-hangzhou8>
<华东 2上海cn-shanghai7>
<华南 1>
<华南 2河源cn-heyuan2>
<华南 3广州cn-guangzhou2>
<西南 1成都cn-chengdu2>
如果我们用<.+> 来提取,会显示只有一个符合的,整个一大段都符合,这是为什么呢?
因为此时正则表达式的贪婪模式是开启的,因此会会尽可能多的匹配内容。这时候这段文本开头的“<”和文本最末尾的 “>”会构成一个完整的符合搜索条件的内容,因此,匹配只会出现一个match(即一个符合的选项)
要修改很简单,在”<.+>”内部的“+”号后面添加一个问号(?)即可以使用非贪婪模式,这样再运行一遍,就可以分割开来了,如下,可以看见,现在我们出现了11个match。
花括号表示 前面的字符匹配 指定的次数
例如下面的文本:
1,11,111,1111,11111,111111
表达式1{2}表示匹配连续的“1”两次,如下,一共出现了9个符合的
如果在花括号里面再加一个数字,例如表达式1{4,5}。就会寻找有出现连续的“1”最少4次,最多5次的符合选项。如下,最后有三个match
假设有下方字符串:
'<华北 1青岛.cn-qingdao2>
<华北 2北京.cn-beijing8>
<华北 3张家口.cn-zhangjiakou3>
<华北 5呼和浩特.cn-huhehaote2>
<华北 6乌兰察布.cn-wulanchabu2>
<华东 1杭州.cn-hangzhou8>
<华东 2上海.cn-shanghai7>
<华南 1><华南 2河源.cn-heyuan2>
<华南 3广州.cn-guangzhou2>
<西南 1成都.cn-chengdu2>'
我们提取. 点号后面的文本(包括点号)
这时我们如果使用…?或者…+就会发现,根本无法选择我们想要的,因为.点号是作为一个特殊符号表示要匹配除了 换行符 之外的任何 单个 字符.因此这里我们需要用反斜杠来转义,所以得写成…*,如下
继续使用上面的例子,我们看看\反斜杠还有什么用途。反斜杠后面接一些字符,表示匹配 某种类型 的一个字符。
\d 匹配0-9之间任意一个数字字符,等价于表达式 [0-9]
\D 匹配任意一个不是0-9之间的数字字符,等价于表达式 [^0-9]
\s 匹配任意一个空白字符,包括 空格、tab、换行符等,等价于表达式 [\t\n\r\f\v]
\S 匹配任意一个非空白字符,等价于表达式 [^ \t\n\r\f\v]
\w 匹配任意一个文字字符,包括大小写字母、数字、下划线,等价于表达式 [a-zA-Z0-9_]
缺省情况也包括 Unicode文字字符,如果指定 ASCII 码标记,则只包括ASCII字母
\W 匹配任意一个非文字字符,等价于表达式 [^a-zA-Z0-9_]
…接下来的点进主页见正则表达式(二)
有疑问滴滴V:mutou88848