python学习–正则表达式
- 2020 年 1 月 13 日
- 筆記
正则表达式是一种用来匹配字符串的强有力的工具它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的。
Python支持的正则表达式元字符和语法:
语法 |
说明 |
实例 |
完整匹配的字符串 |
---|---|---|---|
一般字符 |
匹配自身 |
a1b2c3 |
a1b2c3 |
. |
匹配任意除换行符'n'外的字符 |
l.l |
lol|lpl|lfl |
|
转义字符,使后一个字符改变原来的意思 |
l.ll\l |
l.lll |
[…] |
对应的位置可以是字符集中任意字符,字符集中的字符可以逐个列出,也可以给出范围如[abc]或[a-c],第一个字符如果是^则表示取反如[^abc]表示除abc以外的其他字符;所有特殊字符在字符集中都是去其原有特殊意义 |
a[bcd]e |
abeaceade |
d |
数字:[0-9] |
adc |
a2c |
D |
非数字:[^d] |
aDc |
axc |
s |
空白字符:[空格,trnfv] |
asc |
a c |
S |
非空白字符:[^s] |
|
|
w |
单词字符:[_a-zA-Z0-9] |
awc |
axc |
W |
非单词字符:[^w] |
aWc |
a c |
---|---|---|---|
* |
匹配前一个字符0或无限次 |
abc* |
ababcccccc |
+ |
匹配前一个字符1或无限次 |
abc+ |
abcabcccccc |
? |
匹配前一个字符0或1次 |
abc? |
ababc |
{m} |
匹配前一个字符m次 |
ab{2}c |
abbc |
{m,n} |
匹配前一个字符m至n次;若省略m,匹配0至n次;若省略n,匹配m至无限次 |
ab{1,2}c |
abcabbc |
*? +? ??{m,n}? |
使* + ? {m,n}变成非贪婪模式 |
|
|
^ |
匹配字符串开头在多行模式中匹配每一行的开头 |
^abc |
abc |
$ |
匹配字符串末尾在多行模式中匹配每一行的末尾 |
abc$ |
abc |
A |
仅匹配字符串开头 |
Aabc |
abc |
Z |
仅匹配字符串末尾 |
abcZ |
abc |
---|---|---|---|
b |
匹配一个单词边界,也就是指单词和空格间的位置。例如, 'erb' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。 |
|
|
B |
匹配非单词边界。'erB' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。 |
|
|
| |
左右表达式任意匹配一个总是先尝试匹配左边表达式,一旦匹配成功则跳过匹配右边的表达式 |
abc|def |
abcdef |
(…) |
被括起来的表达式作为分组 |
(abc){2}ab(12|45)c |
abcabcab45c |
(?#…) |
#后的内容作为注释被忽略 |
ab(?#com..)123 |
ab123 |
反斜杠
与大多数编程语言相同,正则表达式里使用""作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r"\"表示。同样,匹配一个数字的"\d"可以写成r"d"。有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
看一个例子:d{3}s+d{3,8}
我们来从左到右解读一下:
d{3}表示匹配3个数字,例如'010';
s可以匹配一个空格(也包括Tab等空白符),所以s+表示至少有一个空格,例如匹配' ',' '等;
d{3,8}表示3-8个数字,例如'1234567'。
综合起来,上面的正则表达式可以匹配以任意个空格隔开的带区号的电话号码。
如果要匹配'010-12345'这样的号码呢?由于'-'是特殊字符,在正则表达式中,要用''转义,所以,上面的正则是d{3}-d{3,8}。
进阶
要做更精确地匹配,可以用[]表示范围,比如:
[0-9a-zA-Z_]可以匹配一个数字、字母或者下划线;
[0-9a-zA-Z_]+可以匹配至少由一个数字、字母或者下划线组成的字符串,比如'a100','0_Z','Py3000'等等;
[a-zA-Z_][0-9a-zA-Z_]*可以匹配由字母或下划线开头,后接任意个由一个数字、字母或者下划线组成的字符串,也就是Python合法的变量;
[a-zA-Z_][0-9a-zA-Z_]{0, 19}更精确地限制了变量的长度是1-20个字符(前面1个字符+后面最多19个字符)。
A|B可以匹配A或B,所以[P|p]ython可以匹配'Python'或者'python'。
^表示行的开头,^d表示必须以数字开头。
$表示行的结束,d$表示必须以数字结束。
你可能注意到了,py也可以匹配'python',但是加上^py$就变成了整行匹配,就只能匹配'py'了。
re模块
re 模块使 Python 语言拥有全部的正则表达式功能。
re.match
re.match 尝试从字符串的开始匹配一个模式。
语法:
re.match(pattern, string, flags=0)
参数说明:
pattern 匹配的正则表达式
string 要匹配的字符串。
flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
匹配成功re.match方法返回一个匹配的对象,否则返回None。
eg:
import re sss = re.match(r'^d{3}-d{3,8}$', '010-12345') print(sss) <_sre.SRE_Match object; span=(0, 9), match='010-12345'>
可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。
group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
eg:
line = "Cats are smarter than dogs" matchObj = re.match(r'(.*) are (.*?) .*', line) if matchObj: print("matchObj.group() : ", matchObj.group()) print("matchObj.groups() : ", matchObj.groups()) print("matchObj.group(1) : ", matchObj.group(1)) print("matchObj.group(2) : ", matchObj.group(2)) else: print("No match!!") matchObj.group() : Cats are smarter than dogs matchObj.groups() : ('Cats', 'smarter') matchObj.group(1) : Cats matchObj.group(2) : smarter
re.search
语法:
re.search(pattern, string, flags=0)
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。
eg:
import re line = "Cats are smarter than dogs" matchObj = re.match(r'are', line) if matchObj: print("are ", matchObj.group()) else: print("No match!!") matchObj = re.search(r'are', line) if matchObj: print("are : ", matchObj.group()) else: print("No match!!") No match!! are : are
切分字符串
语法:
split(string[, maxsplit]) | re.split(pattern, string[, maxsplit]):
按照能够匹配的子串将string分割后返回列表。maxsplit用于指定最大分割次数,不指定将全部分割。
a = re.split(r'd+', 'one1two2three3four') print(a) ['one', 'two', 'three', 'four'] s = re.split(r's+', 'a b c d w') print(s) d = re.split(r'[s,;]+', 'a ,a;b,v g,d , ;') print(d) ['a', 'b', 'c', 'd', 'w'] ['a', 'a', 'b', 'v', 'g', 'd', '']
findall
findall(string[, pos[, endpos]]) | re.findall(pattern, string[, flags])
搜索string,以列表形式返回全部能匹配的子串。
u = re.findall(r'd', 'one1two2three3four4') print(u) ['1', '2', '3', '4']
finditer
finditer(string[, pos[, endpos]]) | re.finditer(pattern, string[, flags])
搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。
u = re.finditer(r'd', 'one1two2three3four4') for i in u: print(i.group()) 1 2 3 4
re.sub用于替换字符串中的匹配项。
语法:
re.sub(pattern, repl, string, max=0)
返回的字符串是在字符串中用 RE 最左边不重复的匹配来替换。如果模式没有发现,字符将被没有改变地返回。
可选参数 count 是模式匹配后替换的最大次数;count 必须是非负整数。缺省值是 0 表示替换所有的匹配
#!/usr/bin/python import re phone = "2004-959-559 # This is Phone Number" num = re.sub(r'#.*', "", phone) print(num) nun = re.sub(r'D', "", num) print(nun) 2004-959-559 2004959559
正则表达式非常强大,要讲清楚正则的所有内容,可以写一本厚厚的书了。如果你经常遇到正则表达式的问题,你可能需要一本正则表达式的参考书。