进阶第七课 Python模块之re

在学习re模块之前,请大家先学习正则表达式的基础知识。-_-!!

re是Python中负责处理正则表达式的一个模块。其他编程语言中没有re!但是正则表达式并不是Python的专利,很多语言中都有涉及。

正则表达式30分钟入门教程

http://deerchao.net/tutorials/regex/regex.htm

一定要仔细读完,吃透以后再往下看。我看了2个小时才看了一半。。。30分钟的作者骗人那。。。-__-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

后半段粗略看,文章结尾时,笔者说本文30分钟看不懂。。

 

另一个推荐一个链接:

https://github.com/zeeshanu/learn-regex/blob/master/README-cn.md

网页提供练习工具。全文转发。

注:这个链接中表达式左侧是以prec(php)的语法规则书写的,链接中的“在线练习”可以切换至python,格式有所不同。

 什么是正则表达式?

正则表达式是一组由字母和符号组成的特殊文本, 它可以用来从文本中找出满足你想要的格式的句子.

一个正则表达式是在一个主体字符串中从左到右匹配字符串时的一种样式. "Regular expression"这个词比较拗口, 我们常使用缩写的术语"regex"或"regexp". 正则表达式可以从一个基础字符串中根据一定的匹配模式替换文本中的字符串、验证表单、提取字符串等等.

想象你正在写一个应用, 然后你想设定一个用户命名的规则, 让用户名包含字符,数字,下划线和连字符,以及限制字符的个数,好让名字看起来没那么丑. 我们使用以下正则表达式来验证一个用户名:

以上的正则表达式可以接受 john_doejo-hn_doejohn12_as. 但不匹配Jo, 因为它包含了大写的字母而且太短了.

1、基本匹配

正则表达式其实就是在执行搜索时的格式, 它由一些字母和数字组合而成. 例如: 一个正则表达式 the, 它表示一个规则: 由字母t开始,接着是h,再接着是e.

 

"the" => The fat cat sat on the mat.

 

正则表达式123匹配字符串123. 它逐个字符的与输入的正则表达式做比较.

正则表达式是大小写敏感的, 所以The不会匹配the.

"The" => The fat cat sat on the mat.

 

2. 元字符

正则表达式主要依赖于元字符. 元字符不代表他们本身的字面意思, 他们都有特殊的含义. 一些元字符写在方括号中的时候有一些特殊的意思. 以下是一些元字符的介绍:

元字符描述
. 句号匹配任意单个字符除了换行符.
[ ] 字符种类. 匹配方括号内的任意字符.
[^ ] 否定的字符种类. 匹配除了方括号里的任意字符
* 匹配>=0个重复的在*号之前的字符.
+ 匹配>=1个重复的+号前的字符.
? 标记?之前的字符为可选.
{n,m} 匹配num个大括号之前的字符 (n <= num <= m).
(xyz) 字符集, 匹配与 xyz 完全相等的字符串.
| 或运算符,匹配符号前或后的字符.
\ 转义字符,用于匹配一些保留的字符 [ ] ( ) { } . * + ? ^ $ \ |
^ 从开始行开始匹配.
$ 从末端开始匹配.

2.1 点运算符 .

.是元字符中最简单的例子. .匹配任意单个字符, 但不匹配换行符. 例如, 表达式.ar匹配一个任意字符后面跟着是ar的字符串.

".ar" => The car parked in the garage.

 

2.2 字符集

字符集也叫做字符类. 方括号用来指定一个字符集. 在方括号中使用连字符来指定字符集的范围. 在方括号中的字符集不关心顺序. 例如, 表达式[Tt]he 匹配 the 和 The.

"[Tt]he" => The car parked in the garage.

 

方括号的句号就表示句号. 表达式 ar[.] 匹配 ar.字符串

"ar[.]" => A garage is a good place to park a car.

 

2.2.1 否定字符集

一般来说 ^ 表示一个字符串的开头, 但它用在一个方括号的开头的时候, 它表示这个字符集是否定的. 例如, 表达式[^c]ar 匹配一个后面跟着ar的除了c的任意字符.

"[^c]ar" => The car parked in the garage.

 

2.3 重复次数

后面跟着元字符 +* or ? 的, 用来指定匹配子模式的次数. 这些元字符在不同的情况下有着不同的意思.

2.3.1 * 号

*号匹配 在*之前的字符出现大于等于0次. 例如, 表达式 a* 匹配以0或更多个a开头的字符, 因为有0个这个条件, 其实也就匹配了所有的字符. 表达式[a-z]* 匹配一个行中所有以小写字母开头的字符串.

"[a-z]*" => The car parked in the garage #21.

 

*字符和.字符搭配可以匹配所有的字符.**和表示匹配空格的符号\s连起来用, 如表达式\s*cat\s*匹配0或更多个空格开头和0或更多个空格结尾的cat字符串.

"\s*cat\s*" => The fat cat sat on the concatenation.

 

2.3.2 + 号

+号匹配+号之前的字符出现 >=1 次. 例如表达式c.+t 匹配以首字母c开头以t结尾,中间跟着任意个字符的字符串.

"c.+t" => The fat cat sat on the mat.

 

2.3.3 ? 号

在正则表达式中元字符 ? 标记在符号前面的字符为可选, 即出现 0 或 1 次. 例如, 表达式 [T]?he 匹配字符串 he 和 The.

"[T]he" => The car is parked in the garage.

 

"[T]?he" => The car is parked in the garage.

 

2.4 {} 号

在正则表达式中 {} 是一个量词, 常用来一个或一组字符可以重复出现的次数. 例如, 表达式 [0-9]{2,3} 匹配最少 2 位最多 3 位 0~9 的数字.

"[0-9]{2,3}" => The number was 9.9997 but we rounded it off to 10.0.

 

我们可以省略第二个参数. 例如, [0-9]{2,} 匹配至少两位 0~9 的数字.

如果逗号也省略掉则表示重复固定的次数. 例如, [0-9]{3} 匹配3位数字

"[0-9]{2,}" => The number was 9.9997 but we rounded it off to 10.0.

 

"[0-9]{3}" => The number was 9.9997 but we rounded it off to 10.0.

 

2.5 (...) 特征标群

特征标群是一组写在 (...) 中的子模式. 例如之前说的 {} 是用来表示前面一个字符出现指定次数. 但如果在 {} 前加入特征标群则表示整个标群内的字符重复 N 次. 例如, 表达式 (ab)* 匹配连续出现 0 或更多个 ab.

我们还可以在 () 中用或字符 | 表示或. 例如, (c|g|p)ar 匹配 car 或 gar 或 par.

"(c|g|p)ar" => The car is parked in the garage.

 

2.6 | 或运算符

或运算符就表示或, 用作判断条件.

例如 (T|t)he|car 匹配 (T|t)he 或 car.

"(T|t)he|car" => The car is parked in the garage.

 

2.7 转码特殊字符

反斜线 \ 在表达式中用于转码紧跟其后的字符. 用于指定 { } [ ] / \ + * . $ ^ | ? 这些特殊字符. 如果想要匹配这些特殊字符则要在其前面加上反斜线 \.

例如 . 是用来匹配除换行符外的所有字符的. 如果想要匹配句子中的 . 则要写成 \. 以下这个例子 \.?是选择性匹配.

"(f|c|m)at\.?" => The fat cat sat on the mat.

 

2.8 锚点

在正则表达式中, 想要匹配指定开头或结尾的字符串就要使用到锚点. ^(键盘上与数字6在同一键帽上的字符) 指定开头, $ 指定结尾.

2.8.1 ^ 号

^ 用来检查匹配的字符串是否在所匹配字符串的开头,也就是第一个“词”(其实是第一个字符串)

例如, 在 abc 中使用表达式 ^a 会得到结果 a. 但如果使用 ^b 将匹配不到任何结果. 因为在字符串 abc 中并不是以 b 开头.

例如, ^(T|t)he 匹配以 The 或 the 开头的字符串.

"(T|t)he" => The car is parked in the garage. 
"^(T|t)he" => The car is parked in the garage. #只匹配了第一个The,中间的the并未匹配。因为the不是这一串字符的第一个“词”(字符串)

2.8.2 $ 号

同理于 ^ 号, $ 号用来匹配字符是否是最后一个,也就是最后一个“词”(其实是最后一个字符串)

例如, (at\.)$ 匹配以 at. 结尾的字符串.

"(at\.)" => The fat cat. sat. on the mat.
"(at\.)$" => The fat cat. sat. on the mat. #只匹配了最后一个at. 中间的at.因为不是这一串字符的最后一个“词”(字符串)

3. 简写字符集

正则表达式提供一些常用的字符集简写. 如下:

简写描述
. 除换行符外的所有字符
\w 匹配所有字母数字, 等同于 [a-zA-Z0-9_]
\W 匹配所有非字母数字, 即符号, 等同于: [^\w]
\d 匹配数字: [0-9]
\D 匹配非数字: [^\d]
\s 匹配所有空格字符, 等同于: [\t\n\f\r\p{Z}]
\S 匹配所有非空格字符: [^\s]
\f 匹配一个换页符
\n 匹配一个换行符
\r 匹配一个回车符
\t 匹配一个制表符
\v 匹配一个垂直制表符
\p 匹配 CR/LF (等同于 \r\n),用来匹配 DOS 行终止符

4. 前后关联约束(前后预查)

前置约束和后置约束都属于非捕获簇(用于匹配不在匹配列表中的格式). 前置约束用于判断所匹配的格式是否在另一个确定的格式之后.

例如, 我们想要获得所有跟在 $ 符号后的数字, 我们可以使用正向向后约束 (?<=\$)[0-9\.]*. 这个表达式匹配 $ 开头, 之后跟着 0,1,2,3,4,5,6,7,8,9,. 这些字符可以出现大于等于 0 次.

前后关联约束如下:

符号描述
?= 前置约束-存在
?! 前置约束-排除
?<= 后置约束-存在
?<! 后置约束-排除

4.1 ?=... 前置约束(存在)

?=... 前置约束(存在), 表示第一部分表达式必须跟在 ?=...定义的表达式之后.

返回结果只满足第一部分表达式. 定义一个前置约束(存在)要使用 (). 在括号内部使用一个问号和等号: (?=...).

前置约束的内容写在括号中的等号后面. 例如, 表达式 (T|t)he(?=\sfat) 匹配 The 和 the, 在括号中我们又定义了前置约束(存在) (?=\sfat) ,即 The 和 the 后面紧跟着 (空格)fat.

"(T|t)he(?=\sfat)" => The fat cat sat on the mat.

4.2 ?!... 前置约束-排除

前置约束-排除 ?! 用于筛选所有匹配结果, 筛选条件为 其后不跟随着定义的格式 前置约束-排除 定义和 前置约束(存在) 一样, 区别就是 = 替换成 ! 也就是 (?!...).

表达式 (T|t)he(?!\sfat) 匹配 The 和 the, 且其后不跟着 (空格)fat.

"(T|t)he(?!\sfat)" => The fat cat sat on the mat.

4.3 ?<= ... 后置约束-存在

后置约束-存在 记作(?<=...) 用于筛选所有匹配结果, 筛选条件为 其前跟随着定义的格式. 例如, 表达式 (?<=(T|t)he\s)(fat|mat) 匹配 fat 和 mat, 且其前跟着 The 或 the.

"(?<=(T|t)he\s)(fat|mat)" => The fat cat sat on the mat.

4.4 ?<!... 后置约束-排除

后置约束-排除 记作 (?<!...) 用于筛选所有匹配结果, 筛选条件为 其前不跟着定义的格式. 例如, 表达式 (?<!(T|t)he\s)(cat)匹配 cat, 且其前不跟着 The 或 the.

"(?<!(T|t)he\s)(cat)" => The cat sat on cat.

5. 标志

标志也叫修饰语, 因为它可以用来修改表达式的搜索结果. 这些标志可以任意的组合使用, 它也是整个正则表达式的一部分.

标志描述
i 忽略大小写.
g 全局搜索.
m 多行的: 锚点元字符 ^ $ 工作范围在每行的起始.

5.1 忽略大小写 (Case Insensitive)

修饰语 i 用于忽略大小写. 例如, 表达式 /The/gi 表示在全局搜索 The, 在后面的 i 将其条件修改为忽略大小写, 则变成搜索 the 和 Theg 表示全局搜索.

"The" => The fat cat sat on the mat.
"/The/gi" => The fat cat sat on the mat.

5.2 全局搜索 (Global search)

修饰符 g 常用语执行一个全局搜索匹配, 即(不仅仅返回第一个匹配的, 而是返回全部). 例如, 表达式 /.(at)/g 表示搜索 任意字符(除了换行) + at, 并返回全部结果.

"/.(at)/" => The fat cat sat on the mat.
"/.(at)/g" => The fat cat sat on the mat.

5.3 多行修饰符 (Multiline)

多行修饰符 m 常用语执行一个多行匹配。

像之前介绍的 (^,$) 用于检查格式是否是在待检测字符串的开头或结尾. 但我们如果想要它在每行的开头和结尾生效, 我们需要用到多行修饰符 m。

例如, 表达式 /at(.)?$/gm 表示小写字符 a 后跟小写字符 t , 末尾可选除换行符外任意字符. 根据 m 修饰符, 现在表达式匹配每行的结尾。

"/.at(.)?$/" => The fat
                cat sat
                on the mat.

"/.at(.)?$/gm" => The fat
                  cat sat
on the mat.





好了。看完这些,下面转一篇大神的有关re的详细介绍。
https://www.cnblogs.com/yyyg/p/5498803.html
下面是全文转发。

Python 的 re 模块(Regular Expression 正则表达式)提供各种正则表达式的匹配操作,和 Perl 脚本的正则表达式功能类似,使用这一内嵌于 Python 的语言工具,尽管不能满足所有复杂的匹配情况,但足够在绝大多数情况下能够有效地实现对复杂字符串的分析并提取出相关信息。Python 会将正则表达式转化为字节码,利用 C 语言的匹配引擎进行深度优先的匹配。

表 1. 正则表达式元字符和语法
符号说明实例
. 表示任意字符,如果说指定了 DOTALL 的标识,就表示包括新行在内的所有字符。 'abc'  >>>'a.c'   >>>结果为:'abc' 
^ 表示字符串开头。 'abc'  >>>'^abc'  >>>结果为:'abc'
$ 表示字符串结尾。 'abc'  >>>'abc$'  >>>结果为:'abc'
*, +, ? '*'表示匹配前一个字符重复 0 次到无限次,'+'表示匹配前一个字符重复 1次到无限次,'?'表示匹配前一个字符重复 0 次到1次

'abcccd'  >>>'abc*' >>>结果为:'abccc'

'abcccd' >>>'abc+'  >>>结果为:'abccc'

'abcccd' >>>'abc?'  >>>结果为:'abc'

*?, +?, ??    前面的*,+,?等都是贪婪匹配,也就是尽可能多匹配,后面加?号使其变成惰性匹配即非贪婪匹配

'abc'  >>>'abc*?' >>>结果为:'ab'

'abc'  >>>'abc??' >>>结果为:'ab'

'abc'  >>>'abc+?' >>>结果为:'abc'

{m} 匹配前一个字符 m 次 'abcccd' >>>'abc{3}d'  >>>结果为:'abcccd'
{m,n} 匹配前一个字符 m 到 n 次 'abcccd'  >>> 'abc{2,3}d' >>>结果为:'abcccd'
{m,n}? 匹配前一个字符 m 到 n 次,并且取尽可能少的情况  'abccc'  >>> 'abc{2,3}?' >>>结果为:'abcc'
\ 对特殊字符进行转义,或者是指定特殊序列  'a.c' >>>'a\.c' >>> 结果为: 'a.c'
[]                  表示一个字符集,所有特殊字符在其都失去特殊意义,只有: ^  -  ]  \   含有特殊含义 'abcd' >>>'a[bc]' >>>结果为:'ab'
| 或者,只匹配其中一个表达式 ,如果|没有被包括在()中,则它的范围是整个正则表达式 'abcd' >>>'abc|acd' >>>结果为:'abc'
( … ) 被括起来的表达式作为一个分组. findall 在有组的情况下只显示组的内容  'a123d' >>>'a(123)d' >>>结果为:'123'
(?#...) 注释,忽略括号内的内容  特殊构建不作为分组  'abc123' >>>'abc(?#fasd)123' >>>结果为:'abc123'
(?= … ) 表达式’…’之前的字符串,特殊构建不作为分组 在字符串’ pythonretest ’中 (?=test) 会匹配’ pythonre ’
(?!...) 后面不跟表达式’…’的字符串,特殊构建不作为分组 如果’ pythonre ’后面不是字符串’ test ’,那么 (?!test) 会匹配’ pythonre ’
(?<= … ) 跟在表达式’…’后面的字符串符合括号之后的正则表达式,特殊构建不作为分组 正则表达式’ (?<=abc)def ’会在’ abcdef ’中匹配’ def ’
(?:) 取消优先打印分组的内容 'abc' >>>'(?:a)(b)' >>>结果为'[b]'
?P<> 指定Key 'abc' >>>'(?P<n1>a)>>>结果为:groupdict{n1:a}
表 2. 正则表达式特殊序列
特殊表达式序列说明
\A 只在字符串开头进行匹配。
\b 匹配位于开头或者结尾的空字符串
\B 匹配不位于开头或者结尾的空字符串
\d 匹配任意十进制数,相当于 [0-9]
\D 匹配任意非数字字符,相当于 [^0-9]
\s 匹配任意空白字符,相当于 [ \t\n\r\f\v]
\S 匹配任意非空白字符,相当于 [^ \t\n\r\f\v]
\w 匹配任意数字和字母,相当于 [a-zA-Z0-9_]
\W 匹配任意非数字和字母的字符,相当于 [^a-zA-Z0-9_]
\Z 只在字符串结尾进行匹配

上面提到贪婪匹配和非贪婪匹配请看例子:

>>> import re
>>> #贪婪
>>> ret_greed=re.findall(r'a(\d+)','a23b')
>>> print(ret_greed)
['23']
>>> #非贪婪
>>> ret_no_greed=re.findall(r'a(\d+?)','a23b')
>>> print(ret_no_greed)
['2']

由于贪婪匹配为尽可能的多匹配所以结果为23 ,有人好奇了,findall是什么鬼 ,请耐心往下看:

re模块

正则表达式使用反斜杠” \ “来代表特殊形式或用作转义字符,这里跟Python的语法冲突,因此,Python用” \\ “表示正则表达式中的” \ “,因为正则表达式中如果要匹配” \ “,需要用\来转义,变成” \ “,而Python语法中又需要对字符串中每一个\进行转义,所以就变成了” \\ “。

上面的写法是不是觉得很麻烦,为了使正则表达式具有更好的可读性,Python特别设计了原始字符串(raw string),需要提醒你的是,在写文件路径的时候就不要使用raw string了,这里存在陷阱。raw string就是用’r’作为字符串的前缀,如 r”\n”:表示两个字符”\”和”n”,而不是换行符了。Python中写正则表达式时推荐使用这种形式。

1、 re.findall(pattern, string[, flags]):

 方法能够以列表的形式返回能匹配的子串。先看简单的例子:

>>> import re
>>> a='one1two2three3four4'
>>> ret=re.findall(r'(\d+)',a)
>>> print(ret)
['1', '2', '3', '4']

从上面的例子可以看出返回的值是个列表,并且返回字符串中所有匹配的字符串。

2、re.finditer(pattern, string[, flags])

搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。 请看例子:

>>> import re
>>> p=re.compile(r'\d+')
>>> for m in p.finditer('one1two2three3four4'):
        print(m.group())

    
1
2
3
4

3、re.match和re.search

Python提供了两种不同的原始操作:match和search。match是从字符串的起点开始做匹配,而search(perl默认)是从字符串做任意匹配。看个例子:

>>> import re
>>> ret_match=re.match("c","abcde") #从字符串开头匹配,匹配到返回match的对象,匹配不到返回None
>>> if(ret_match):
        print("ret_match:"+ret_match.group())
    else:
        print("ret_match:None")

    
ret_match:None

>>> ret_search = re.search("c","abcde")  #扫描整个字符串返回第一个匹配到的元素并结束,匹配不到返回None
>>> if(ret_search):
    
        print("ret_search:"+ret_search.group())

        
ret_search:c

re.match对象拥有以下方法:

>>> import re
>>> a='123abc456'
>>> ret_match=re.match("a","abcde")
>>> print(ret_match.group())  #返回返回被 RE 匹配的字符串
a
>>> print(ret_match.start())  #返回匹配开始的位置
0
>>> print(ret_match.end())    #返回匹配结束的位置
1
>>> print(ret_match.span())   #返回一个元组包含匹配 (开始,结束) 的位置
(0, 1)

其中group()方法可以指定组号,如果组号不存在则返回indexError异常看如下例子:

>>> import re
>>> a='123abc456'
>>> re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(0)   #123abc456,返回整体默认返回group(0)
'123abc456'
>>> re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(1)   #123
'123'
>>> re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(2)   #abc
'abc'
>>> re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(3)   #456
'456'

4、re.sub和re.subn

 两种方法都是用来替换匹配成功的字串,值得一提的时,sub不仅仅可以是字符串,也可以是函数。subn函数返回元组,看下面例子:

>>> import re
>>> #sub
>>> ret_sub = re.sub(r'(one|two|three)','ok','one word two words three words') #ok word ok words ok words
>>> #subn
>>> ret_subn = re.subn(r'(one|two|three)','ok','one word two words three words') #('ok word ok words ok words', 3) 3,表示替换的次数
>>> print(ret_sub)
ok word ok words ok words
>>> print(ret_subn)
('ok word ok words ok words', 3)

5、re.split(pattern, string, maxsplit=0)

通过正则表达式将字符串分离。如果用括号将正则表达式括起来,那么匹配的字符串也会被列入到list中返回。maxsplit是分离的次数,maxsplit=1分离一次,默认为0(0?下面的例子中如果不输入maxsplit这个参数,结果是把要处理的字符串整个给分解了。下面我添加了示例,maxsplit的值0和4的结果相同),不限制次数。看一下例子:

>>> import re
>>> ret = re.split('\d+','one1two2three3four4') #匹配到1的时候结果为'one'和'two2three3four4',匹配到2的时候结果为'one', 'two'和'three3four4', 所以结果为:
>>> ###output###
>>> print(ret)
['one', 'two', 'three', 'four', '']
>>> ret = re.split('\d+','one1two2three3four4',maxsplit=0)
>>> print(ret)
['one', 'two', 'three', 'four', '']
>>> ret = re.split('\d+','one1two2three3four4',maxsplit=4)
>>> print(ret)
['one', 'two', 'three', 'four', '']

 

6、re.compile(strPattern[, flag])

这个方法是Pattern类的工厂方法,用于将字符串形式的正则表达式编译为Pattern对象。第二个参数flag是匹配模式,取值可以使用按位或运算符’|’表示同时生效,比如re.I | re.M。另外,你也可以在regex字符串中指定模式,比如re.compile(‘pattern’, re.I | re.M)与re.compile(‘(?im)pattern’)是等价的。可选值有:

6.1 re.I(IGNORECASE): 忽略大小写(括号内是完整写法,下同)

6.2 re.M(MULTILINE): 多行模式,改变'^''$'的行为

6.3 re.S(DOTALL): 点任意匹配模式,改变'.'的行为
6.4 re.L(LOCALE): 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定
6.5 re.U(UNICODE): 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性
6.6 re.X(VERBOSE): 详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释。

请看例子:

>>> 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))
['JGood', 'cool']

re 小结

re.match()

re.search()
re.findall()
re.split()
re.sub()
re.match()、re.search()可以分为两种情况,第一种不分组第二种分组(方便记忆):
>>> import re
>>> a = 'hello word diao zha tian'
>>> ret = re.match('h\w+',a)
>>> print(ret.group()) #获取匹配到的所有结果
hello
>>> print(ret.groups()) # 获取模型中匹配到的分组情况
()
>>> print(ret.groupdict())# 获取模型中匹配到的分组结果
{}

>>> ret = re.match('(?P<n>h)(?P<n1>\w+)',a)
>>> print(ret)
<_sre.SRE_Match object; span=(0, 5), match='hello'>
>>> print(ret.group()) #获取匹配到的所有结果
hello
>>> print(ret.groups()) # 获取模型中匹配到的分组情况
('h', 'ello')
>>> print(ret.groupdict())# 获取模型中匹配到的分组结果
{'n': 'h', 'n1': 'ello'}

re.findall()

>>> import re
>>> a = 'hello alex alex adn acd'
>>> n = re.findall('(a)(\w+)',a)  #[('a', 'lex'), ('a', 'lex'), ('a', 'dn'), ('a', 'cd')]
>>> print(n)
[('a', 'lex'), ('a', 'lex'), ('a', 'dn'), ('a', 'cd')]

re.split()

在编写计算器的时候可以用re.split() 比如:

>>> def f1(ex):
    
        return eval(ex)  #测试用 真实中要自己编写四则运算

>>> a = '1*2+(5/6)+(12*23)/15'
>>> while True:
    ret=re.split('\(([^()]+)\)', a, 1)
    if len(ret)==3:
        a,b,c=re.split('\(([^()]+)\)',a,1)
        rec=f1(b)
        a=a+str(rec)+c
    else:
        red=f1(a)
        print(red)
        break

    
21.23333333333333

 re.sub()  用于替换匹配的字符串

>>> import re
>>> content = "123abc456"
>>> new_content = re.sub('\d+', 'sb', content)
>>> # new_content = re.sub('\d+', 'sb', content, 1)
>>> print(new_content)
sbabcsb

 

本课总结:当上述内容你仔细看过,且亲手敲过这些代码那么现在你一定对Python的正则表达式用法已经有了一定的认知。不用急,正则不是一天就能学会的,本课内容也无法涵盖所有的示例。我会不断增加示例,让我们一起学习,共同进步。加油!!!

另外剧透一下:今后会演示如何做计算器程序。实际上在编写计算器的过程中,就是使用正则表达式的过程。比如:

计算:25-(18*9+(35-20)/5-100+20*10)+70-5*20

在这个算式中:只有5种符号(初期不考虑输入错误的情况),分别是0-9、+、-、*、/和()。关键是怎样告诉程序先计算哪个,后计算哪个;也就是告诉程序如何判断计算顺序。有了准确的计算顺序后,剩下的就没什么啦。

posted @ 2018-03-30 19:38  驼背蜗牛  阅读(379)  评论(0编辑  收藏  举报