正则相关知识点

1.正则表达式

1.什么是正则表达式

   一套规则 与匹配字符串的一套规则

2.能做什么?

  1.检测一个输入的字符串是否合法。

    • 用户输入一个内容的时候,我们要提前做检测

    • 能够提高程序的效率并且减轻服务器的压力

  2.从一个大文件中找到符合规则的内容 

    • 能够高效的从一大段文字中快速找到符合规则的内容           

3.正则规则

  -  所有的规则中的字符就可以刚好匹配到字符串中的内容

4.字符串

  -  在同一个位置可能出现的各种字符组成了一个字符组,在正则表达式中用[]表示

  -  接受范围,可以描述多个范围,连着写就可以了

   - [abc] 一个中括号只表示一个字符位置(匹配a或者b或者c)

2.所有的元字符

    \d   表示匹配所有的数字
    \w   表示匹配数字,字母,下换线  
    \s   表示匹配所有的空白
    \t   表示匹配制表符tab
    \n   表示匹配换行符\n 回车键
    \D   表示匹配非数字
    \W   表示匹配非数字,字母,下换线
    \S   表示匹配非空白
    .    除\n以外所有的
    []   匹配字符组中的字符
    [^]  匹配除字符组中字符的所有字符
    ^    匹配字符串的开始
    $    匹配字符串的结尾
    ( )  匹配括号内的表达式,也表示一个组
    a|b  匹配字符a或者字符b

3.量词

    ?    重复零次或者一次
    +     重复一次或更多次
    *     重复零次或者多次
    {n}   重复n次
    {n,}  重复n次或更多次
    {n,m} 重复n次或m次

4.贪婪匹配与非贪婪匹配

# 贪婪匹配
  在量词范围允许的情况下,尽量多的匹配内容
  . *x  表示匹配任意字符,任意次数,遇到最后一个x才停下来
# 非贪婪匹配
  . *?x  表示匹配任意字符,任意多次数,但是一旦遇到x就停下来

5.转义符

  原本有特殊意义的字符,为了表达它本身的意义的时候,需要转义
  有一些有特殊 意义的内容,放在字符组中,会取消它的特殊意义
  [().*+?] 所有的内容在字符组中会取消它的特殊意义
  [a-c] -在字符组中表示范围,如果不希望它表示范围,需要转义,或者放在字符组的最前面\最后面

练习题:

18位或者15位的身份证号
# 15位
[1-9]\d{14}
# 18位   
[1-9]\d{16}[\dx]
[1-9]\d{16}[0-9x]

18位或者15位
# ^([1-9]\d{16}[\dx])$|^([1-9]\d{14})$
# ^[1-9]\d{14}(\d{2}[\dx])?$

6.re模块常用的方法  

  findall (正则,待匹配字符串flag):返回所有匹配项的

import re
ret = re.findall("d+","19740ash93010uru") 
# 返回所有满足匹配条件的结果,放在列表里
print(ret)        
# ['19740', '93010']

  search:返回一个变量,通过group取到的是一个匹配的项

ret = re.search('\d+','19740ash93010uru')   
if ret:
    print(ret.group())
# 函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以
通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
# 19740

ret = re.search('9(\d)(\d)','19740ash93010uru')
print(ret)  # 变量
# <_sre.SRE_Match object; span=(1, 4), match='974'>
if ret:
    print(ret.group())
    print(ret.group(1))
    print(ret.group(2))

# 输出结果展示
974
7
4
    
# search 只取第一个符合条件的,没有优先显示这件事,得到的结果是一个变量。
# 变量.group() 的结果完全和变量.group(0)的结果一致
# 变量.group(n) 的形式指定获取第n个分组中匹配到的内容

  为什么在search 中不需要分优先级,而在findall中需要?

    加上括号是为了对真正需要的内容进行提取

import re
ret = re.findall('<\w+>(\w+)</\w+>','<h1>askh930s02391j192agsj</h1>')
print(ret)
# ['askh930s02391j192agsj']


ret = re.search('<(\w+)>(\w+)</\w+>','<h1>askh930s02391j192agsj</h1>')
print(ret.group())
print(ret.group(1))
print(ret.group(2))
# <h1>askh930s02391j192agsj</h1>
# h1
# askh930s02391j192agsj

     为什么要用分组,以及fildall的分组优先到底有什么好处

import re
exp = "2-3*(5+6)"
# a+b 或者是 a-b 并且计算他们的结果
ret = re.search("\d+[+,-]\d",exp).group()
print(ret,type(ret))
if ret[1] == "-":
    a, b = ret.split("-")
    print(int(a) + int(b))
else:
    a, b = ret.split("+")
    print(int(a) + int(b))
# 输出结果为: 5
# 利用正则表达式 ret = re.search('(\d+)[+](\d+)',exp) print(int(ret.group(1)) + int(ret.group(2)))
# 输出结果: 5

    分组和findall的现象

# 分组和findall的现象
    # 为什么要用分组?
        # 把想要的内容放分组里

# 如何取消分组优先 # 如果在写正则的时候由于不得已的原因,导致不要的内容也得写在分组里 # (?:) 取消这个分组的优先显示

   macth:从头开始找第一个,其他和search一样

import re 
ret = re.match('a', 'abc').group()  # 同search,不过尽在字符串开始处进行匹配
print(ret)
# 'a'

# 用户输入的内容匹配的时候,需要用户输入11位数手机号码,^手机号码$match("手机号正则$","123eva456taibai")search("^手机号正则$","123eva456taibai")

   compile(正则):同一个正则表达式需要多次使用的时候提前编译来节省时间

# 假如同一个正则表达式要被使用多次,使用compile节省了多次解析同一个正则表达式的时间

ret = re.compile("\d+")
res1 = ret.search("alex37176")
res2 = ret.findall("alex37176")
print(res1)
print(res2)
# <_sre.SRE_Match object; span=(4, 9), match='37176'>
# ['37176']

  finditer :返回一个迭代器,通过迭代器取到的是一个变量,通过group取值(节省空间)

ret = re.finditer('\d+','agks123ak018g093')
for i in ret:
    print(i.group())
# 123
# 018
# 093 

# 通过compile节省时间,在通过finditer节省空间
ret = re.compile("\d+")
res = ret.finditer('agks123ak018as093')
for i in res:
    print(i.group())
    
# 123
# 018
# 093 

  split:通过正则表达式匹配的内容进行分割

import re
ret = re.split("\d+","eva3egon4yuan")
print(ret)
# ['eva', 'egon', 'yuan']
      
ret = re.split("(\d+)",,"eva3egon4yuan")
print(ret)
# ['eva', '3', 'egon', '4', 'yuan'

  在匹配部分加上()之后所切出的结果是不同的,没有 () 的没有保留所匹配的项,但是有 () 的却能够保留了匹配的项,这个在某些需要保留匹配部分的使用过程是非常重要的。

   sub:替换,通过正则表达式匹配的内容进行替换

import re
ret = re.sub("\d+","H","aas123dfghj147")
print(ret)
# aasHdfghjH
      
ret = re.sub("\d+","H",,"aas123dfghj147",1)    # 替换一个
print(ret)
# "aasHdfghj147

  subn      替换,在sub的基础上,返回一个元组,第一个内容是替换结果,第二个是替换次数

import re
ret = re.subs("\d+","H",'alex123wusir456')
print(ret)
# ('alexHwusirH', 2)

7.分组命名

1.分组命名

import re
ret = re.search('\d(\d)\d(?P<name3>\w+?)(\d)(\w)\d(\d)\d(?P<name1>\w+?)(\d)(\w)\d(\d)\d(?P<name2>\w+?)(\d)(\w)','123abc45678agsf_123abc45678agsf123abc45678agsf')

print(ret.group("name1"))
# agsf_123abc

print(ret.group("name2"))
# agsf

分组命名的基本格式
# (?P<名字>正则表达式)
# ret.group('名字')

2.分组命名的引用

import re
exp= '<abc>akd7008&(&*)hgdwuih</abc>008&(&*)hgdwuih</abd>'
ret= re.search('<(?P<tag>\w+)>.*?</(?P=tag)>',exp)
print(ret.group())

# <abc>akd7008&(&*)hgdwuih</abc>

import re
exp= '<abc>akd7008&(&*)hgdwuih</abc>008&(&*)hgdwuih</abd>'
ret= re.search(r'<(\w+)>.*?</\1>',exp)
ret= re.search('<(\w+)>.*?</\\1>',exp)
print(ret)

练习题:

匹配出所有的整数部分
import re
ret=re.findall(r"\d+\.\d+|(\d+)","1-2*(60+(-40.35/5)-(-4*3))")
ret = filter(lambda n:n,ret)
print(list(ret))
# ['1', '2', '60', '5', '4', '3']


# 分组命名(?P<组名>正则  (?p=组名))
# 有时候我们要匹配的内容是包含在不想要的内容之中的,只能先把不想要的内容匹配出来,然后再想办法从结果中去掉

 

待续

posted @ 2019-12-15 16:32  菜鸟学小白  阅读(265)  评论(0编辑  收藏  举报
ヾ(≧O≦)〃嗷~