关于Python的正则表达式,初步学习了下,感觉跟shell脚本的正则表达式大体相同,先来做个小结吧!
正则表达式
正则表达式在实际的文本文件处理中,经常用到,其实正则表达式并不是Python的一部分,其它语言中都有。正则表达式是用于处理字符串的强大工具,拥有自己独特的语法以及一个独立的处理引擎,效率上可能不如str自带的方法,但功能真的十分强大。得益于这一点,在提供了正则表达式的语言里,正则表达式的语法都是一样的,区别只在于不同的编程语言实现支持的语法数量不同;但不用担心,不被支持的语法通常是不常用的部分。如果已经在其他语言里使用过正则表达式,只需要简单看一看就可以上手了。
下图展示了使用正则表达式进行匹配的流程:
从上图我们可以看出,正则表达式的大致匹配过程是:依次拿出表达式和文本中的字符比较,如果每一个字符都能匹配,则匹配成功;一旦有匹配不成功的字符则匹配失败。如果表达式中有量词或边界,这个过程会稍微有一些不同,但也是很好理解的,来看看下面的这个正则表达式模式。
ID | 模式 | 描述 |
---|---|---|
1 | ^ | 匹配字符串的开头 |
2 | $ | 匹配字符串的末尾。 |
3 | . | 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。 |
4 | […] | 用来表示一组字符,单独列出:[amk] 匹配 ‘a’,’m’或’k’ |
5 | [^…] | 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。 |
6 | * | 匹配0个或多个的表达式。 |
7 | + | 匹配1个或多个的表达式。 |
8 | ? | 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式 |
9 | { n,} | 精确匹配n个前面表达式。 |
10 | {n,m} | 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式 |
11 | (re) | G匹配括号内的表达式,也表示一个组 |
12 | (?imx) | 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。 |
13 | (?-imx) | 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。 |
14 | (?:re) | 类似 (…), 但是不表示一个组 |
15 | (?imx:re) | 在括号中使用i, m, 或 x 可选标志 |
16 | (?-imx:re) | 在括号中不使用i, m, 或 x 可选标志 |
17 | (?#…) | 注释. |
18 | (?=re) | 前向肯定界定符。如果所含正则表达式,以 … 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。 |
19 | (?!re) | 前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功 |
20 | (?>re) | 匹配的独立模式,省去回溯。 |
21 | \w | 匹配字母数字,等价于’[A-Za-z0-9_]’ |
22 | \W | 匹配非字母数字, [^A-Za-z0-9_]’ |
23 | \s | 匹配任意空白字符,等价于[\t\n\r\f]. |
24 | \S | 匹配任意非空字符,等价于[^ \f\n\r\t\v] |
25 | \d | 匹配任意数字,等价于[0-9]. |
26 | \D | 匹配任意非数字,等价于[^0-9]。 |
27 | \A | 匹配字符串开始 |
28 | \Z | 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。c |
29 | \z | 匹配字符串结束 |
30 | \G | 匹配最后匹配完成的位置。 |
31 | \b | 匹配一个单词边界,也就是指单词和空格间的位置。例如, ‘er\b’ 可以匹配”never” 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’。 |
32 | \B | 匹配非单词边界。’er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’。 |
33 | \n, \t, 等. | 匹配一个换行符。匹配一个制表符。等 |
34 | \1…\9 | 匹配第n个分组的子表达式。 |
35 | \10 | 匹配第n个分组的子表达式,如果它经匹配。否则指的是八进制字符码的表达式。 |
下面从正则表达式的几个函数/方法来简单介绍下正则表达式的用法。
re.match()函数
re.match 尝试从字符串的开头匹配一个模式,如:下面的例子匹配第一个单词。
1 | import re |
输出:
This
This
re.match的函数原型为:re.match(pattern, string, flags)
- 第一个参数是正则表达式,这里为”(\w+)\s”,如果匹配成功,则返回一个Match,否则返回一个None;
- 第二个参数表示要匹配的字符串;
- 第三个参数是标致位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
re.search()函数
re.search函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回,如果字符串没有匹配,则返回None。
1 | import re |
输出结果:
beautiful i
re.search的函数原型为: re.search(pattern, string, flags)
每个参数的含意与re.match一样。
re.match()与re.search()的区别
re.match只匹配字符串的开始,如果字符串从一开始就不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。
请看下面这个实例:
1 | import re |
match会从字符串起始出进行模式匹配,即模式中的其实字母‘g’匹配‘This’中的‘T’,所以,匹配失败。
No match!!
如果使用的是search,来看看结果:
1 | m = re.search( r'girl', line, re.M|re.I) |
以上实例运行结果如下:
search --> m.group() : girl
re.sub() & re.subn()函数
re.sub用于替换字符串中的匹配项。下面一个例子将字符串中的空格 ‘ ‘ 替换成 ‘-‘ :
1 | import re |
输出:
I-like-Cats-more-than-dogs!
re.sub的函数原型为:re.sub(pattern, repl, string, count)
其中第二个函数是替换后的字符串;本例中为’-‘
第四个参数指替换个数。默认为0,表示每个匹配项都替换。
re.sub还允许使用函数对匹配项的替换进行复杂的处理。如:re.sub(r’\s’, lambda m: ‘[‘ + m.group(0) + ‘]’, text, 0);将字符串中的空格’ ‘替换为’[ ]’。
注:re.subn和re.sub大体相似,唯一不同的就是返回结果,subn会将匹配的个数也显示出来。
如:
1 | >>>import re |
re.split()函数
可以使用re.split来分割字符串,如:re.split(r’-‘, text);将字符串按’-‘符号分割成一个单词列表。
1 | import re |
输出:
['I', 'really', 'like', 'this', 'girl!']
re.findall()函数
re.findall可以获取字符串中所有匹配的字符串。如:re.findall(r’\w*i\w*‘, text);获取字符串中,包含’oo’的所有单词。
1 | import re |
输出结果:
['like', 'this', 'girl']
re.compile()函数
可以把正则表达式编译成一个正则表达式对象。可以把那些经常使用的正则表达式编译成正则表达式对象,这样可以提高一定的效率。下面是一个正则表达式对象的一个例子:
1 | import re |
分别输出下列信息:
'very'
['very', 'her', 'very']
This is a [very] beautiful girl, I like [her] [very] much.
邮箱验证
使用Python写一个简单的邮箱验证的正则表达式:
根据csu.ldw@csu.edu.cn来填写规则
规则:
- @前面可以有’.’, ‘_’, ‘-‘, 但不能出现在头尾,而且不能连续出现
- @后面到结尾之间,可以有多个子域名
- 邮箱的结尾为2~5个字母,比如cn、com、name等
1 | #-*- coding: utf-8 -*- |
测试输出:
csu.ldw@csu.edu.cn
当m = regex.match(“_csu.ldw@csu.edu.cn“)
当邮箱为:
_csu.ldw@csu.edu.cn
csu.ldw_@csu.edu.cn
csu.ldw@csu_.edu.cn
_csu.ldw@csu.edu.cn1
都不会匹配
提示:合法邮箱的规则可能不够完善,这里就简单的匹配这三个规则吧!