转自https://www.cnblogs.com/mosson/articles/5821825.htm

正则本身就是一门语言:

  正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串,在文本处理方面功能非常强大,也经常用作爬虫,来爬取特定内容,Python本身不支持正则,但是通过导入re模块,Python也能用正则表达式,下面就来讲一下python正则表达式的用法。

下图列出了Python支持的正则表达式元字符和语法:

一、Python正则的字符:

1、普通字符:

  大多数的字符和字母都会和自身匹配

2、元字符:

  元字符:.   ^   $   *   +   ?   { }   [ ]   |   ( )  \

2.1、[]详解

  例如,[abc] 将匹配"a", "b", 或 "c"中的任意一个字符;也可以用区间[a-c]来表示同一字符集,和前者效果一致。如果你只想匹配小写字母,那么 RE 应写成 [a-z].

2.2()详解

1

2

3

4

5

6

7

8

>>> p = re.compile('(a(b)c)d')

>>> m = p.match('abcd')

>>> m.group(0)

'abcd'

>>> m.group(1)

'abc'

>>> m.group(2)

'b'

2.3:+、*、?、{}详解

  贪婪模式和非贪婪模式:

  从前面的描述可以看到'*','+'和'?'都是贪婪的,但这也许并不是我们说要的,所以,可以在后面加个问号,将策略改为非贪婪,只匹配尽量少的RE。示例,

1

2

3

4

5

体会两者的区别:  <STRONG>findall 只匹配输出 分组内容如果是分组的话,如果不是分组的话都输出匹配到输出的内容</STRONG>   后面介绍

>>> re.findall(r"a(\d+?)","a234b"# 非贪婪模式  如果\d+匹配的是两个数字的话,

        ['2']

>>> re.findall(r"a(\d+)","a234b")

        ['234']<BR>

正则匹配的时候的 r 的作用

1

2

3

4

>>> re.findall(r"\bI","I love u")           

['I']

>>> re.findall(r"\bIl","Ilove u")

['Il']

二、re模块的各种方法

1、findall  (获取字符串中所有的匹配字符串)

findall(),可以将匹配到的结果以列表的形式返回,如果匹配不到则返回一个空列表,下面来看一下代码中的使用

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

import re

l=re.findall(r'\d','4g6gggg9,9')             # \d代表数字,将匹配到的元素放到一个列表里

print(l)                                     # ['4', '6', '9', '9']

  

print(re.findall(r'\w','ds.._ 4'))           # ['d', 's', '_', '4'],匹配字母数字下划线

  

print(re.findall(r'^sk','skggj,fd,7'))       #  以sk开头的,['sk']

  

print(re.findall(r'^sk','kggj,fd,7'))        # []

  

print(re.findall(r'k{3,5}','ffkkkkk'))       # 取前面一个字符‘k'的3到5次,['kkkkk']

  

print(re.findall(r'a{2}','aasdaaaaaf'))      # 匹配前一个字符a两次,['aa', 'aa', 'aa']

  

print(re.findall(r'a*x','aaaaaax'))          # ['aaaaaax'] 匹配前面一个字符0次或多次,贪婪匹配

  

print(re.findall(r'\d*''www33333'))        # ['', '', '', '33333', '']

  

print(re.findall(r'a+c','aaaacccc'))         # ['aaaac'] 匹配前面一个字符的一次或多次,贪婪匹配

  

print(re.findall(r'a?c','aaaacccc'))         # ['ac', 'c', 'c', 'c'] 匹配前面一个字符的0次或1次

  

print(re.findall(r'a[.]d','acdggg abd'))     # .在[]里面失去了意义,所以结果为[]

  

print(re.findall(r'[a-z]','h43.hb -gg'))     # ['h', 'h', 'b', 'g', 'g']

  

print(re.findall(r'[^a-z]','h43.hb -gg'))    # 取反,['4', '3', '.', ' ', '-']

  

print(re.findall(r'ax$','dsadax'))           # 以'ax'结尾 ['ax']

  

print(re.findall(r'a(\d+)b','a23666b'))      # ['23666']

  

print(re.findall(r'a(\d+?)b','a23666b'))     # ['23666']前后均有限定条件,则非贪婪模式失效

  

print(re.findall(r'a(\d+)','a23b'))          # ['23']

  

print(re.findall(r'a(\d+?)','a23b'))         # [2] 加上一个?变成非贪婪模式

find 的高级用法:?:

  默认是取分组()内的信息,但是我想让分组外的匹配信息也取到,就要用到 ?:

1

2

3

4

5

>>> import re

>>> re.findall(r"www.(baidu|laonanhai).com","sdfsd www.baidu.comwww.laonanhai.com")

['baidu''laonanhai']

>>> re.findall(r"www.(?:baidu|laonanhai).com","sdfsd www.baidu.comwww.laonanhai.com")

['www.baidu.com''www.laonanhai.com']

finditer():迭代查找

1

2

3

4

5

6

7

8

9

>>> p = re.compile(r'\d+')

>>> iterator = p.finditer('12 drumm44ers drumming, 11 ... 10 ...')

>>> for match in iterator:

...  match.group() , match.span()

... 

('12', (02))

('44', (810))

('11', (2426))

('10', (3133))

2、match(pattern, string, flag=0)

  • 正则表达式
  • 要匹配的字符串
  • 标志位,用于控制正则表达式的匹配方式

Match对象是一次匹配的结果,包含了很多关于此次匹配的信息,可以使用Match提供的可读属性或方法来获取这些信息。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

方法:

1.group([group1, …]):

获得一个或多个分组截获的字符串;指定多个参数时将以元组形式返回。group1可以使用编号也可以使用别名;编号0代表整个匹配的子串;不填写参数时,返回group(0);没有截获字符串的组返回None;截获了多次的组返回最后一次截获的子串。

2.groups([default]):

以元组形式返回全部分组截获的字符串。相当于调用group(1,2,…last)。default表示没有截获字符串的组以这个值替代,默认为None

3.groupdict([default]):

返回以有别名的组的别名为键、以该组截获的子串为值的字典,没有别名的组不包含在内。default含义同上。

4.start([group]):

返回指定的组截获的子串在string中的起始索引(子串第一个字符的索引)。group默认值为0

5.end([group]):

返回指定的组截获的子串在string中的结束索引(子串最后一个字符的索引+1)。group默认值为0

6.span([group]):

返回(start(group), end(group))。

7.expand(template):

将匹配到的分组代入template中然后返回。template中可以使用\id或\g<id>、\g<name>引用分组,但不能使用编号0。\id与\g<id>是等价的;但\10将被认为是第10个分组,如果你想表达\1之后是字符'0',只能使用\g<1>0

3、search(pattern, string, flag=0)

根据模型去字符串中匹配指定内容,匹配单个,只匹配一次,可以结合split 将匹配到内容分割 拼接 然后再次循环查找。因为findall尽管可以找到所有,但是在处理分组()时候分组外的内容匹配不到。而findall是返回列表 后面会有介绍

4、grouop和groups

group(0)  显示全部

group(1)  显示第一个分组()

group(2)  显示第二个分组()

如果没有分组或超出分组个数就会报错

5、sub(pattern, repl, string, count=0, flag=0)

用于替换匹配的字符串 pattern内必须为正则表达式,不能是正则表达式search或findall 查找到的赋值变量

  比如我的计算器处理括号的方法,用正则search匹配到后,不能直接将变量出入 sub的pattern,因为不起作用

sub 疑点

sub(repl, string[, count]) | re.sub(pattern, repl, string[, count]):

使用repl替换string中每一个匹配的子串后返回替换后的字符串。 
当repl是一个字符串时,可以使用\id或\g<id>、\g<name>引用分组,但不能使用编号0。 
当repl是一个方法时,这个方法应当只接受一个参数(Match对象),并返回一个字符串用于替换(返回的字符串中不能再引用分组)。

subn方法  返回总共替换的次数

1

2

>>> re.subn(r'\d','ZZ','23*,5sfds.6hsdf')

('ZZZZ*,ZZsfds.ZZhsdf'4)

subn(repl, string[, count]) |re.sub(pattern, repl, string[, count]): 

返回 (sub(repl, string[, count]), 替换次数)。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

import re 

= re.compile(r'(\w+) (\w+)')

= 'i say, hello world!'

   

print p.subn(r'\2 \1', s)

   

def func(m):

    return m.group(1).title() + ' ' + m.group(2).title()

   

print p.subn(func, s)

   

### output ###

# ('say i, world hello!', 2)

# ('I Say, Hello World!', 2)

 6、split(pattern, string, maxsplit=0, flags=0)

split(string[, maxsplit]) | re.split(pattern, string[, maxsplit]): 
按照能够匹配的子串将string分割后返回列表。maxsplit用于指定最大分割次数,不指定将全部分割。

1

2

3

4

5

6

import re   

= re.compile(r'\d+')

print p.split('one1two2three3four4')

   

### output ###

# ['one', 'two', 'three', 'four', '']

7  re.compile(strPattern[, flag]): compile 编译方法

如果一个匹配规则,以后要使用多次,就可以先将其编译,以后就不用每次都在去写匹配规则

  这个方法是Pattern类的工厂方法,用于将字符串形式的正则表达式编译为
Pattern对象。 第二个参数flag是匹配模式,取值可以使用按位或运算符'|'
表示同时生效,比如re.I | re.M
  可以把正则表达式编译成一个正则表达式对象。可以把那些经常使用的正则
表达式编译成正则表达式对象,这样可以提高一定的效率。下面是一个正则表达式
对象的一个例子:

1

2

3

4

import re

text = "JGood is a handsome boy, he is cool, clever, and so on..."

regex = re.compile(r'\w*oo\w*')

print regex.findall(text)   #查找所有包含'oo'的单词

三、原生字符串、编译、分组

1、原生字符串

细心的人会发现,我每一次在写匹配规则的话,都在前面加了一个r,为什么要这样写,下面从代码上来说明,

1

2

3

4

5

6

7

import re

#“\b”在ASCII 字符中代表退格键,\b”在正则表达式中代表“匹配一个单词边界”

print(re.findall("\bblow","jason blow cat"))    #这里\b代表退格键,所以没有匹配到

  

print(re.findall("\\bblow","jason blow cat"))   #用\转义后这里就匹配到了 ['blow']

  

print(re.findall(r"\bblow","jason blow cat"))   #用原生字符串后就不需要转义了 ['blow']

你可能注意到我们在正则表达式里使用“\d”,没用原始字符串,也没出现什么问题。那是因为ASCII 里没有对应的特殊字符,所以正则表达式编译器能够知道你指的是一个十进制数字。但是我们写代码本着严谨简单的原理,最好是都写成原生字符串的格式。

2、编译

如果一个匹配规则,我们要使用多次,我们就可以先将其编译,以后就不用每次都在去写匹配规则,下面来看一下用法

1

2

3

import re

c=re.compile(r'\d')                             #以后要在次使用的话,只需直接调用即可

print(c.findall('as3..56,'))                    #['3', '5', '6']

3、分组

除了简单地判断是否匹配之外,正则表达式还有提取子串的强大功能。用()表示的就是要提取的分组,可以有多个组,分组的用法很多,这里只是简单的介绍一下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

import re

print(re.findall(r'(\d+)-([a-z])','34324-dfsdfs777-hhh'))        # [('34324', 'd'), ('777', 'h')]

  

print(re.search(r'(\d+)-([a-z])','34324-dfsdfs777-hhh').group(0))    # 34324-d 返回整体

print(re.search(r'(\d+)-([a-z])','34324-dfsdfs777-hhh').group(1))    # 34324 获取第一个组

print(re.search(r'(\d+)-([a-z])','34324-dfsdfs777-hhh').group(2))    # d 获取第二个组

print(re.search(r'(\d+)-([a-z])','34324-dfsdfs777-hhh').group(3))    # IndexError: no such group

  

print(re.search(r"(jason)kk\1","xjasonkkjason").group())         #\1表示应用编号为1的组 jasonkkjason

  

print(re.search(r'(\d)gg\1','2j333gg3jjj8').group())                 # 3gg3 \1表示使用第一个组\d

  

# 下面的返回None 为什么是空?而匹配不到3gg7,因为\1的不仅表示第一组,而且匹配到的内容也要和第一组匹配到的内容相同,第一组匹配到3,第二组匹配到7 不相同所以返回空

print(re.search(r'(\d)gg\1','2j333gg7jjj8'))

  

print(re.search(r'(?P<first>\d)abc(?P=first)','1abc1'))              # 1abc1 声明一个组名,使用祖名引用一个组 

  

r=re.match('(?P<n1>h)(?P<n2>\w+)','hello,hi,help')  # 组名的另外一种用法

print(r.group())                                # hello 返回匹配到的值

print(r.groups())                               # ('h', 'ello')返回匹配到的分组

print(r.groupdict())                            # {'n2': 'ello', 'n1': 'h'} 返回分组的结果,并且和相应的组名组成一个字典

  

# 分组是从已经匹配到的里面去取值

origin ="hello alex,acd,alex"

print(re.findall(r'(a)(\w+)(x)',origin))                  # [('a', 'le', 'x'), ('a', 'le', 'x')]

print(re.findall(r'a\w+',origin))                         # ['alex', 'acd', 'alex']

print(re.findall(r'a(\w+)',origin))                       # ['lex', 'cd', 'lex']

print(re.findall(r'(a\w+)',origin))                       # ['alex', 'acd', 'alex']

print(re.findall(r'(a)(\w+(e))(x)',origin))               # [('a', 'le', 'e', 'x'), ('a', 'le', 'e', 'x')]

  

r=re.finditer(r'(a)(\w+(e))(?P<name>x)',origin)

for in r :

    print(i,i.group(),i.groupdict())

'''

    [('a', 'le', 'e', 'x'), ('a', 'le', 'e', 'x')]

    <_sre.SRE_Match object; span=(6, 10), match='alex'> alex {'name': 'x'}

    <_sre.SRE_Match object; span=(15, 19), match='alex'> alex {'name': 'x'}

'''

  

print(re.findall('(\w)*','alex'))                   # 匹配到了alex、但是4次只取最后一次即 x 真实括号只有1个

print(re.findall(r'(\w)(\w)(\w)(\w)','alex'))       # [('a', 'l', 'e', 'x')]  括号出现了4次,所以4个值都取到了

  

origin='hello alex sss hhh kkk'

print(re.split(r'a(\w+)',origin))                   # ['hello ', 'lex', ' sss hhh kkk']

print(re.split(r'a\w+',origin))                     # ['hello ', ' sss hhh kkk']

Python正则表达式快速入门相关推荐

  1. python正则表达式快速入门_Python学习笔记——正则表达式入门

    标签: # 本文对正则知识不做详细解释,仅作入门级的正则知识目录. 正则表达式的强大早有耳闻,大一时参加一次选拔考试,题目就是用做个HTML解析器,正则的优势表现得淋漓尽致.题外话不多讲,直接上干货: ...

  2. python快速入门答案-总算懂得python脚本快速入门教程

    PyQt5是基于Digia公司强大的图形程式框架Qt5的python接口,由一组python模块构成.PyQt5本身拥有超过620个类和6000函数及方法.在可以运行于多个平台.PyQt5拥有双重协议 ...

  3. python flask快速入门与进阶 百度云_Python Flask快速入门与进阶

    课程目录 1-1 Python Flask快速入门与进阶.mp4 2-1 windows环境安装开发环境 (上).mp4 2-2 windows环境安装开发环境 (下).mp4 2-3 配置开发环境. ...

  4. 正则表达式快速入门,转载

    正则表达式快速入门 首先简单介绍下正则表达式: 在编写处理字符串的程序或网页时,经常会有查找符合某些复杂规则的字符串的需要.正则表达式就是用于描述这些规则的工具.换句话说,正则表达式就是记录文本规则的 ...

  5. Python语言快速入门(上)

    前言 首先需要说明的是,本期图文仅涉及Python语言的基础入门内容,由于我也不是计算机本专业的学生,这些内容完全是出于强烈的学业兴趣而撰写的,其中难免会出现一些表述不恰当的地方,如果存在问题,欢迎我 ...

  6. Python语言快速入门上

    目录 1.前言 2.变量和常量 1)Python对象模型 2)Python变量 二.运算符和表达式 [运算符和表达式] [位运算符] [逻辑运算符] [成员运算符] [身份运算符] [常用内置函数] ...

  7. Python语言快速入门(下)

    前言 本图文是本期图文的下篇,可能篇幅较长大概有10000多字,很高兴您能阅读,也感谢您的关注支持!这期下篇主要还是接着上次的内容继续,在上篇中我介绍了关于Python环境的安装.基本数据处理.输入输 ...

  8. python做erp系统教程_“python2.7教程廖雪峰“刚开始学openERP Python,如何快速入门?...

    为什么廖雪峰的JS教程不如Python 教程 娃娃哈 廖雪峰python教程在哪 这是他的网址:www.liaoxuefeng.com 这是python专有python2.7,python3,可供选择 ...

  9. python脚本教程-总算懂得python脚本快速入门教程

    PyQt5是基于Digia公司强大的图形程式框架Qt5的python接口,由一组python模块构成.PyQt5本身拥有超过620个类和6000函数及方法.在可以运行于多个平台.PyQt5拥有双重协议 ...

  10. Python 程序设计快速入门简易教程

    Python 程序设计快速入门简易教程 Python语言快速检索 一些需要知道的事 一个简单的Python程序 Python的基本数据类型 Python的基本运算符 Python的常用函数 impor ...

最新文章

  1. 多态amp;nbsp;OC——第十天
  2. Algorithm:C++语言实现之链表相关算法(单链公共结点问题、一般LCA、括号匹配、最长括号匹配、逆波兰表达式Reverse Polish Notation、直方图矩形面积、收集雨水问题)
  3. strtok(), strtok_s() 字符串分割函数
  4. ef mysql modelfirst_Entity Framework(EF的Model First方法)
  5. Java sdk及tomcat安装设置
  6. 计算机文化基础第三版龙天才课后答案,龙天才
  7. java多线程通信基础(面向厕所编程)
  8. 杀不死的人狼——我读《人月神话》(四)
  9. Python+OpenCV:图像Shi-Tomasi角点检测器
  10. Netty in action—第一个Netty应用
  11. 三阶魔方还原步骤图_五阶魔方还原教程——层先法
  12. 计算机二级英语简历里怎么写,简历计算机水平怎么写
  13. 【ANSYS】网格划分技术之映射网格
  14. 顺流交易会计处理的通俗理解
  15. python爬虫学习(1)__抓取煎蛋图片
  16. 微信公众号给微信用户推送信息 模板信息
  17. 面试攻略!Java 基础面试 100 问
  18. 端点科技春招笔试回忆(Java方向)
  19. 关于猜数字游戏以及关机指令
  20. 考虑下面特殊的整数线性规划问题max求和 求和 为非负整数

热门文章

  1. Java NIO 中的非阻塞究竟体现在哪里?
  2. win 10 右键新建offic失效问题
  3. Orcad Pspice仿真
  4. C++实现堆排序算法
  5. VS2010中文版莫名的错误
  6. python + selenium 之网银爬虫
  7. 数学分析教程(科大)——6.3笔记+习题
  8. 如何做好高端的总结汇报PPT呢?
  9. Node.js+Express+MongoDB 建站实例
  10. jconsole远程连接的使用