Python知识小结------正则表达式

一、前言

      在平日的的文本查找中,我们只要按下Crtl-F就可以进行内容查找。而正则表达式则是将你要查找的内容固定成为一个“模式”,我们在做查找时会十分方便。

例如:我们要判断一串数字是否为电话号码时,使用正则表达式和不使用正则表达式的情况。我们知道电话号码的模式是:400-555-4567

不使用正则表达式:

def isPhoneNumber(text):
    if len(text)!=12:   #判断长度是否为12位
        return False
    for i in range(0,3):
        if not text[i].isdecimal():   #判断前三位是否为数字
            return False
    if text[3]!='-':     #判断第四位是否为‘-’
        return False
    for i in range(4,7):
        if not text[i].isdecimal():   #判断5到7位是否为数字
            return False
    if text[7]!='-':                 #判断第八位是否为‘-’
        return False
    for i in range(8,12):
        if not text[i].isdecimal():   #判断9到12位是否为数字
            return False
    return True

使用正则表达式:

import re 
phoneNumRegex = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d')
mo = phoneNumRegex.search("400-555-4567")
if mo ==None:
    print("没有找到")
else:
    print("匹配成功!"+mo.group())

       首先从代码量来看,使用正则表达式的代码很简洁,执行效率是很快的。而传统代码需要对每一个字符进行判断,其中多次使用if判断和for循环,只要有一处有问题就会输出fasle。如果数据量过大的话,其执行效率就会变低,因此使用正则表达式是十分有效的。

二、re模块简介

       聊到Python正则表达式的支持,首先肯定会想到 re 库,这是一个Python处理文本的 标准库。

标准库 的意思表示这是一个 Python内置模块 ,不需要额外下载,目前Python内置模块大概有300个。可以在这里查看Python所有的内置模块:https://docs.python.org/3/py-modindex.html#cap-r

因为re是内置模块,所以不需要再下载,使用时直接引入即可:

import re

re模块官方文档:https://docs.python.org/zh-cn/3.8/library/re.html

三、常用的正则字符和规则

### 常用元字符 ###
1 .:匹配任何一个字符;
2 ^:匹配除去所列首个字符外的所有字符; ^\d表示必须以数字开头。
3 $:匹配字符串的尾部字符  \d$表示必须以数字结束
4 []:由一对方括号括起来的字符,表明一个字符集合,能够匹配包含在其中的任意一个字符。’-‘ 减号来指定一个字符集合的范围。例子:[a-zA-Z][^a-zA-Z]
5 | 将两个规则并列起来,注意是匹配两边所有的规则 
    要匹配 ‘I have a dog’或’I have a cat’,需要写成r’I have a (?:dog|cat)’ ,而不能写成 r’I have a dog|cat’
5 (?: )  如果想限定它的有效范围,必需使用一个无捕获组 ‘(?: )’包起来
6 \d  匹配数字,这是一个以’\’开头的转义字符,’\d’表示匹配一个数字,即等价于[0-9]
7 \D 匹配非数字 这个是上面的反集,即匹配一个非数字的字符,等价于[^0-9]。注意它们的大小写
   下面我们还将看到Python的正则规则中很多转义字符的大小写形式,代表互补的关系。
8 \w 匹配字母和数字 匹配所有的英文字母和数字,即等价于[a-zA-Z0-9]。 \W  等价 [^a-zA-Z0-9]
9 \s 匹配间隔符  即匹配空格符、制表符、回车符等表示分隔意义的字符,它等价于[ \t\r\n\f\v]。(注意最前面有个空格)  补集:  \S 
10 \A 匹配字符串开头  匹配字符串的开头。它和’^’的区别是,’\A’只匹配整个字符串的开头,即使在’M’模式下,它也不会匹配其它行的行首。
11 \Z 匹配字符串结尾  匹配字符串的结尾。它和’$’的区别是,’\Z’只匹配整个字符串的结尾,即使在’M’模式下,它也不会匹配其它各行的行尾。
12 \b’ 匹配单词边界  它匹配一个单词的边界,比如空格等,不过它是一个‘0’长度字符,它匹配完的字符串不会包括那个分界的字符。
       而如果用’\s’来匹配的话,则匹配出的字符串中会包含那个分界符
13 \B 匹配非边界 它同样是个0长度字符。re.findall( r’\Bbc\w+’ , s )     #匹配包含’bc’但不以’bc’为开头的单词
    ['bcde']  #成功匹配了’abcde’中的’bcde’,而没有匹配’bcd’
14 (?# ) 注释 Python允许你在正则表达式中写入注释
### 重复 规则 ###
15 *   0或多次匹配  
16 +  1次或多次匹配  表示匹配前面的规则至少1次,可以多次匹配
17 ?  0或1次匹配 只匹配前面的规则0次或1次
### 精确匹配和最小匹配  ###
18 {m}    精确匹配m次
   {m,n}  匹配最少m次,最多n次。(n>m)  指定最少3次:{3,}  最大为5次:{,5}
    例子: re.findall( r’\b\d{3}\b’ , s )            # 寻找3位数
19 ‘*?’ ‘+?’ ‘??’ 最小匹配
   ‘*’ ‘+’ ‘?’通常都是尽可能多的匹配字符(贪婪匹配)。有时候我们希望它尽可能少的匹配。
   #例子 re.match(r'^(\d+)(0*)$', '102300').groups()  #('102300', '') 
   #     re.match(r'^(\d+?)(0*)$', '102300').groups() #('1023', '00')
   
### 前向界定与后向界定 ###
20 (?<=…) 前向界定  括号中’…’代表你希望匹配的字符串的前面应该出现的字符串。
    前向界定括号中的表达式必须是常值,也即你不可以在前向界定的括号里写正则式
    re.findall( r’(?<=[a-z]+)\d+(?=[a-z]+)' , s )          # 错误的用法
21 (?=…)  后向界定
   不过如果你只要找出后面接着有字母的数字,你可以在后向界定写正则式:
   re.findall( r’\d+(?=[a-z]+)’, s )
22 (?<!...) 前向非界定
只有当你希望的字符串前面不是’…’的内容时才匹配
23 (?!...) 后向非界定
只有当你希望的字符串后面不跟着’…’内容时才匹配。
### 使用组 ###
24  ()    包含在’()’中的内容,而虽然前面和后面的内容都匹配成功了,却并不包含在结果中,
    用group()或group(0)返回匹配的所有结果,用 group(1),(2)...返回第1,2...个()里面的内容
25  (?(id/name)yes-pattern|no-pattern) 判断指定组是否已匹配,执行相应的规则
    这个规则的含义是,如果id/name指定的组在前面匹配成功了,则执行yes-pattern的正则式,否则执行no-pattern的正则式。

四、简单实例说明

首先明确创建正则表达式的步骤:

1.用import re 导入正则表达式模块

2.用re.compile()函数创建一个Regex对象

3.向Regex对象的search()方法传入想要查找的字符串。它会返回一个Match对象

4.调用Match对象的group方法,返回实际匹配文本的字符串

1.普通正则表达式

import re
#定义一个变量来创建正则表达式
tmp = re.compile(r'hello')
s = tmp.search('goodbye bihao,hellhelowahaha')
if s == None:
    print("么找到")
else:
    print("找到了\n"+s.group())

2.用管道匹配多个分组

        字符|称为“管道”。希望匹配许多个表达式中的一个时,就可以使用它。例如:正则表达式r'1234|yang 中将会匹配出'1234'或者'yang',如果1234和yang都出现在被查找的字符串中,那么第一次匹配出来的文本将会作为Match对象返回。

import re
#管道匹配多个分组
src = re.compile(r'1234|yang')
mo1 = src.search(' yanghuaixu  1236712346534')
mo2 = src.search('1236712346534 yanghuaixu ')
if mo1 == None:
    print("mo1没找到")
else:
    print("mo1找到了:"+mo1.group())
if mo2 == None:
    print("mo2中没有找到")
else:
    print("mo2找打了:"+ mo2.group())

3.用问号实现可选匹配

         有时候,想匹配的模式是可选的,此时需要使用到的符号是?,正则表达式中(wo)?部分表明,wo是可选择的分组,如果要匹配的字符串中有wo,则就匹配出来,如果没有,就不匹配。所以次正则表达式既会匹配policeman,也会匹配policewoman 。

import re
#问号实现可选择匹配
batRegx = re.compile(r'police(wo)?man')
img = batRegx.search('i am a policeman')
if img == None:
    print("没找到img")
else:
    print("img找到了:"+img.group())
img1 = batRegx.search('i am a policewoman')
if img1 == None:
    print("img1没找到")
else:
    print("img1找到了:"+img1.group())

4.用星号匹配零次或者多次

       *意味着正则表达式“匹配零次或者多次”。即星号之前的分组,可以在文本中出现任意次。它可以完全不存在,或一次又一次的重复。则是wo在字符串中出现几次,就匹配几次进行返回。

import re
#用星号匹配零次或者多次
emc = re.compile(r'(wo)*man')
mo2 = emc.search('hello everyone i am a policewoman')
mo3 = emc.search('helloeveryone i am a policewowowowowoman')
if mo2 ==None:
    print("没找到")
else:
    print("mo2找到了:"+mo2.group())
if mo3 == None:
    print("没找到")
else:
    print("mo3找到了:"+mo3.group())

5.用加号匹配一次或者多次

+意味着正则表达式“匹配一次或者多次,但至少要出现一次”。

import re
#用加号匹配一次或者多次
efc = re.compile(r'(wo)+man')
mo3 = efc.search('sdfsfdsadad policeman jiakwokak')
if mo3 == None:
    print("mo3没找到")
else:
    print("mo3找到了:"+mo3.group())
mo4 = efc.search('adiaheiadhi am a policewowowoman hahahahhello')
if mo4 == None:
    print("mo4没找见")
else:
    print("mo4找见了:"+ mo4.group())

6.findall()方法

除了search方法外,Regex对象也有一个findall()方法。search()方法将返回一个Match对象,包含被查找字符串中的"第一次"匹配的文本,而findall()方法将返回一组字符串,包含所有符合匹配的字符串。

import re
#findall方法
arg = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d')
print(arg.findall('400-200-3000 111-111-1111 456-890-0000 666-666-6666'))

7.字符分类

\d可以代表任何数字,也就是说\d是正则表达式(0|1|2|3|4|5|6|7|8|9)的缩写。常见的字符分类如下表:

    缩写字符分类                                        表示
             \d0到9的任何数字
             \D除0到9的数字以外的任何字符
             \w任何字母、数字或下划线字符(可以认为是匹配"单词"字符)
             \W除字母、数字和下划线以外的任何字符
             \s空格、制表符和换行符(可以认为是匹配"空白"字符)
             \S除空格、制表符和换行符以外的任何字符

 

 

 

 

 

 

 

 

import re
#字符分类
mmf = re.compile(r'\d+\s\w+')  #\d+表示匹配一个或多个数字,\s表示匹配一个空白字符,\w+表示匹配一个或多个 字母数字或下划线
print(mmf.findall('1 hello,2,3 world,4aaa,5 _hello,6 HELLO,7 h_ello,8_heello,9 AA9AA'))

8.通配字符

.(句点)表示“通配符”。它可以匹配除了换行之外的所有字符。点-星通配符可以匹配所有的字符串。

import re
#通配字符
mtr = re.compile(r'杨..')
print(mtr.findall('杨树 杨梅 阳光 杨海明 洋洋得意'))

#用点-星匹配所有字符
mtt = re.compile(r'FirstName(.*) LastName(.*)')
mo6 = mtt.search('FirstName: Star LastName: Yang')
print(mo6.group(1))
print(mo6.group(2))

还有点-星通配符的“贪心”模式与“非贪心”模式:贪心模式会匹配到最后一个">"出现所包含的字符串,非贪心模式会匹配到第一次">"出现所包含的字符串

import re
#点-星贪心与非贪心模式:
#非贪心:
notanxin = re.compile(r'<.*?>')
mo7 = notanxin.search('<to server for> dinner>')
print(mo7.group())
#贪心:
tanxin = re.compile(r'<.*>')
mo8 = tanxin.search('<to server for> dinner> hello> 你好>')
print(mo8.group())

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值