python正则表达式
python使用正则表达式之前需要先倒入re模块
import re
可选标志位
re.A |
ASCII,使得 \w,\W,\b,\B,\s 和 \S 只匹配 ASCII 字符,而不匹配完整的 Unicode 字符。这个标志仅对 Unicode 模式有意义,并忽略字节模式。 |
re.I |
IGNORECASE,字符类和文本字符串在匹配的时候不区分大小写 |
re.L |
LOCALE,使得 \w,\W,\b 和 \B 依赖当前的语言(区域)环境,而不是 Unicode 数据库 |
re.M |
MULTILINE,通常 ^ 只匹配字符串的开头,而 $ 则匹配字符串的结尾。当这个标志被设置的时候,^ 不仅匹配字符串的开头,还匹配每一行的行首;& 不仅匹配字符串的结尾,还匹配每一行的行尾。 |
re.S |
DOTALL,使 . 匹配包括换行符在内的所有字符 |
re.X |
VERBOSE,这个标志使你的正则表达式可以写得更好看和更有条理,因为使用了这个标志,空格会被忽略(除了出现在字符类中和使用反斜杠转义的空格);这个标志同时允许你在正则表达式字符串中使用注释,# 符号后边的内容是注释,不会递交给匹配引擎(除了出现在字符类中和使用反斜杠转义的 #)。 |
可以同时使用多个标志位,方法:re.search( r'正则表达式', '字符串', re.M|re.I)
特殊字符
\d |
匹配任何十进制数字;相当于类 [0-9] |
\D |
与 \d 相反,匹配任何非十进制数字的字符;相当于类 [^0-9] |
\s |
匹配任何空白字符(包含空格、换行符、制表符等);相当于 [ \t\n\r\f\v] |
\S |
匹配任何非空白字符;相当于类 [^\t\n\r\f\v] |
\w |
匹配字母数字及下划线 |
\W |
匹配非字母数字及下划线 |
\b |
匹配单词的开始或结束 |
\B |
匹配非单词边界 |
元字符
| |
或操作符,a | b匹配a或b |
^ |
匹配字符串的开头,如果设置了 MULTILINE 标志,就会变成匹配每一行的起始位置。 |
$ |
匹配字符串的末尾。如果设置了 MULTILINE 标志,就会变成匹配每一行的结束位置。 |
. |
匹配任意单个字符,除了换行符,如果设置了DOTALL标志,则可以匹配包括换行符的任意字符。 |
[abc] |
匹配括号中的a,b,c任意单个字符,而不是abc字符串 |
[^abc] |
匹配除了a,b,c之外的任意字符 |
* |
匹配前一个字符0次或多次 |
+ |
匹配前一个字符1次或多次 |
? |
匹配前一个字符0次或1次 |
{n} |
精确匹配前一个字符 n次,例如a{3}b,可以匹配aaab |
{,n} |
匹配前一个字符0次到n次 |
{n,} |
匹配前一个字符 n次到无限次 |
{m,n} |
匹配前一个字符 m 到 n 次 |
\1...\9 |
匹配第n个分组的内容。(abc)小括号括起来的为一组\1匹配第一个小括号的组... |
1.compile函数:用于编译正则表达式,生成一个正则表达式对象
p = re.compile(r'正则表达式'[, 可选标志位]) p.search('待匹配内容').group()
2.match函数:从字符串的起始位置开始匹配,如果起始位置匹配不成功返回none
re.match(r'正则表达式','字符串'[,可选标志位])
匹配对象包含了很多方法和属性,以下几个是最重要的
group() | 返回匹配的字符串 |
start() | 返回匹配的开始位置 |
end() | 返回匹配的结束位置 |
span() | 返回一个元组表示匹配位置(开始,结束) |
3.search函数:扫描整个字符串并返回第一个成功匹配的子串
re.search(r'正则表达式','字符串'[,可选标志位])
匹配对象同样包含了很多方法和属性
group() | 返回匹配的字符串 |
start() | 返回匹配的开始位置 |
end() | 返回匹配的结束位置 |
span() | 返回一个元组表示匹配位置(开始,结束) |
4.findall函数:扫描整个字符串,并返回一个列表,所有成功匹配的子串,如果没有匹配成功返回none
r = re.findall('\d+','111aaa222bbb333ccc') print(r) ['111', '222', '333'] #当正则表达式加上括号时,返回结果会优先显示括号内匹配到的内容 #如果不想要优先显示括号内匹配到的内容,可以在括号内顶格加上?: #(?:正则表达式)
5.finditer函数:和findall类似,成功匹配时返回一个迭代器
p = re.compile('\d+') iterator = p.finditer('3只小甲鱼,15条腿,还有3条去了哪里?') for match in iterator: print (match.group())
6.sub函数:替换,类似字符串的replace
>>> r = re.sub('\d+', 'b', 'aaa111aaa222aaa333') >>> print(r) aaabaaabaaab
7.split函数:切割
>>> r = re.split('\d+','111aaa222bbb333ccc') >>> print(r) ['', 'aaa', 'bbb', 'ccc'] #可以加上切割次数 >>> r = re.split('\d+','111aaa222bbb333ccc',1) >>> print(r) ['', 'aaa222bbb333ccc'] #当需要显示切割的内容时,可以在正则表达式两边加上括号 #打印时会把切割的内容一并显示 >>> r = re.split('(\d+)','111aaa222bbb333ccc') >>> print(r) ['', '111', 'aaa', '222', 'bbb', '333', 'ccc']
8.分组命名
定义分组:(?P<name>正则表达式) 分组引用:(?P=name) >>> r = re.search('(?P<tag><\w+>)(?P<t>\w+)(?P=tag)','<h1>haha<h1>') >>> print(r.group("t")) haha >>> print(r.group("tag")) <h1>
贪婪 VS 非贪婪
当重复一个正则表达式时,如果使用 a*,那么结果是尽可能多地去匹配。当你尝试匹配一对对称的定界符,例如 HTML 标志中的尖括号,默认的贪婪模式会使得你很困扰。
我们来看下例子:
>>> s = '<html><head><title>Title</title>' >>> len(s) 32 >>> print(re.match('<.*>', s).span()) (0, 32) >>> print(re.match('<.*>', s).group()) <html><head><title>Title</title>
RE 匹配在 <html> 的 < 后,.* 消耗掉字符串的剩余部分。由于正则表达式默认是贪婪的原因,RE 必须从字符串的尾部一个字符一个字符地回溯,直到找到匹配的 >。大家看到,按照这种方法,最后找到匹配内容竟是 <html> 的 < 开始,到</title> 的 > 结束。显然这不是你想要的结果。
在这种情况下,解决方案是使用非贪婪的限定符 *?、+?、?? 或 {m, n}?,尽可能地匹配小的文本。
>>> print(re.match('<.*?>', s).group()) <html>