1. 正则表达式语法
1.1 字符与字符类
1.特殊字符:\.^$?+*{}[]()|,以上特殊字符要想使用字面值,必须使用\进行转义
2.字符类:
(1)包含在[]中的一个或者多个字符被称为字符类。字符类内可以指定范围,比如[a-zA-Z0-9]表示a到z,A到Z,0到9之间的任何一个字符。
() 表示原子组;或可以将括号内的东西作为值返回
{} 大括号代表重复数量,[a-z]{1,2}代表一到二个字母,这两个字母都在a到z的范围内
| 匹配两项之间的字符(and),用于查找多个不同值
/ 正则表达式开始和结束的“定界符
\ 转义字符
(2) ^ 放在括号外面表示行的开头, ^\d 表示必须以数字开头。$表示行的结束,\d$表示必须以数字结束.^放在括号里面,表示否定一个字符类,比如[^0-9]表示可以匹配一个任意非数字的字符.
(3)字符类内部可以使用速记法,比如\d \s \w
. 可以匹配除换行符之外的任何字符,如果有re.DOTALL标志,则匹配任意字符包括换行
\d 匹配一个Unicode数字,如果带re.ASCII,则匹配0-9. ‘00\d’可以匹配001,002,003等
\D 匹配Unicode非数字
\s 匹配Unicode空白,如果带有re.ASCII,则匹配\t\n\r\f\v中的一个
\S 匹配Unicode非空白
\w 匹配Unicode单词字符,如果带有re.ASCII,则匹配[a-zA-Z0-9_]中的一个
\W 匹配Unicode非单词字符
1.2 量词
1. ? 匹配前面的字符0次或1次
2. * 匹配前面的字符0次或多次
3. + 匹配前面的字符1次或者多次
4. {m} 匹配前面表达式m次
5. {m,} 匹配前面表达式m次以上
6. {,n} 匹配前面的正则表达式最多n次
7. {m,n} 匹配前面的正则表达式至少m次,最多n次
注意点:以上量词都是贪婪模式,会尽可能多的匹配,如果要改为非贪婪模式,通过在量词后面加一个?来实现
例1: /^[1-9]\d*$/
^[1-9]表示以1到9的某位数字开头
\d*表示0-9的任意一位或者多位
$表示以什么结束
这个正则就表示 以1到9的的某位数字开始并以0-9的任意一位或者多位结尾
如 1 、19、 119、 1110、等等等
例2: \b(\w+)\b\s+\1\b和\b(?:\w+)\b\s+\1\b
\b(\w+)\b\s+\1\b 查找连续重复单词,中间有空格可以被查找到
\b匹配单词的开始
(\w+)匹配单词并存储一份单词 当后面有反向引用时 则可以调用这个存储的单词
\b匹配单词的结束
\s+一个或多个空格
\1这个是反向引用 引用前面括号里存储的单词 也就是 \w+
\b引用单词结束
\b(?:\w+)\b\s+\1\b 表达式无效
(?:\w) 这个单词虽可以被匹配但不会存储一份 后面出现的 \1 也不会调用
例3: program|project和pro(?:gram|ject)
查找"program"和"project"这两个单词
pro(gram|ject)
用了()就表示会匹配括号里存在的内容且存储一份, 用 | 隔开了 也就是说 gram和ject 都被存储了一份 但这样存储的内容是无意义的,所以写成pro(?:gram|ject)更简洁
1.3 组与捕获
1. ()的作用:
(1) 将正则表达式的一部分内容进行组合,以便使用量词或者|
(2) 匹配括号内的内容并进行储存,关掉储存功能需要用到?:
2.反向引用前面()内捕获的内容:
(1)通过组号反向引用:每一个没有使用?:的小括号都会分配一个组好,从1开始,从左到右递增,可以通过\i引用前面()内表达式捕获的内容
(2)通过组名反向引用前面小括号内捕获的内容:可以通过在左括号后面跟随?P<name>,尖括号中放入组名来为一个组起一个别名,后面通过(?P=name)来引用 前面捕获的内容。如(? P<word>\w+)\s+(?P=word)来匹配重复的单词。
3.注意点:反向引用不能放在字符类[]中使用。
1.4 断言与标记
断言不会匹配任何文本,只是对断言所在的文本施加某些约束
1 常用断言:
(1) \b 匹配单词的边界,放在字符类[]中则表示backspace
(2) \B 匹配非单词边界,受ASCII标记影响
(3) ^ 和 $ 分别代表一行的开始和结束
(4) \A 和 \z 分别代表输入的开始和结束位置
(5)(?=exp) 正前瞻 用于匹配的位置前面能匹配到的值
例: hello the world 输入\b\w+(?=ld\b),则会输出wor
(6) (?!exp) 负前瞻 用于匹配值后面不能是exp
例: hello the world 输入\bhe(?!o)\w,则会输出 hel
(7) (?<=exp) 正回顾 用于匹配的位置后面能匹配到的值
例: hello the world 输入(?<=\bhe)\w+\b,则会输出 llo
(8)(?<!exp) 负回顾 用于匹配值前面不能是exp
例: 11122aa aaabbb 输入(?<!\d)[a-z]\w+,,则会输出 aaabbb
1.5 条件匹配
(?(id)yes_exp|no_exp):对应id的子表达式如果匹配到内容,则这里匹配yes_exp,否则匹配no_exp
1.6贪婪匹配与非贪婪匹配
前面的*,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配
#conding=utf-8
import re
a = re.findall(r"a(\d+?)",'a23b')
print(a)
b = re.findall(r"a(\d+)",'a23b')
print(b)
>>['2']
>>['23']
#conding=utf-8
import re
a = re.match('<(.*)>','<H1>title<H1>').group()
print(a)
b = re.match('<(.*?)>','<H1>title<H1>').group()
print(b)
>>><H1>title<H1>
>>><H1>
2. Python正则表达式模块
2.1 正则表达式处理字符串主要有四大功能
1. 匹配 查看一个字符串是否符合正则表达式的语法,一般返回true或者false
2. 获取 正则表达式来提取字符串中符合要求的文本
3. 替换 查找字符串中符合正则表达式的文本,并用相应的字符串替换
4. 分割 使用正则表达式对字符串进行分割。
2.2 正则表达式对象的常用方法
1. re.compile(pattern,flags=0) 可以把那些常用的正则表达式编译成正则表达式对象
re.findall(pattern, string, flags=0) 遍历匹配,可以获取字符串中所有匹配的字符串,返回一个列表
pattern: 编译时用的表达式字符串。
flags 编译标志位,用于修改正则表达式的匹配方式,如:是否区分大小写,多行匹配等。
常用的flags有:
(r 后接字符串表示不转义成字符串)
例:
import re
tt = "Tina is a good girl, she is cool, clever, and so on..."
rr = re.compile(r'\w*oo\w*')
print(rr.findall(tt)) #查找所有包含'oo'的单词
print(re.findall(r'(\w*oo\w*)',tt))
>>> ['good', 'cool']
>>> ['good', 'cool']
2.re.match(pattern, string, flags=0) 从首字母开始开始匹配,string如果开始位置包含匹配项,则匹配成功;若要完全匹配,pattern要以$结尾。
import re
print(re.match('Com','comwww.runcomoob',re.I).group())
>>>com
#coding=utf-8
import re
s = '23432Werwre2342werwrew'
p = r'(\d*)([a-zA-Z]*)'
m = re.match(p,s,re.I)
print(m.group())
print(m.group(0))
print(m.group(1))
print(m.group(2))
print(m.groups())
>>>23432Werwre
>>>23432Werwre
>>>23432
>>>Werwre
>>>('23432', 'Werwre')
group(): 母串中与模式pattern匹配的子串;
group(0):结果与group()一样;
groups():所有group组成的一个元组,group(1)是与patttern中第一个group匹配成功的子串,group(2)是第二个,依次类推,如果index超了边界,抛出IndexError;
3.re.search(pattern, string, flags=0) 在整个字符串内进行匹配,string如果包含1个pattern子串,则匹配成功,返回Match对象,失败则返回None
#coding=utf-8
import re
a = "123abc456"
print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(0)) #123abc456,返回整体
print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(1)) #123
print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(2)) #abc
print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(3)) #456
4.finditer()可以获取字符串中所有匹配的字符串, 并把它们作为一个迭代器返回
#coding=utf-8
import re
tt = "Tina is a good girl, she is cool, clever, and so on..."
mm=re.findall(r'(\w*oo\w*)',tt)
for i in mm:
print(i)
>>>good
>>>cool
5.re.split() 切割字符串
#coding=utf-8
import re
print(re.split('\d+','one1two2three3four4five5'))
print(re.split('\d+','one1two2three3four4five5')[0])
print(re.split('\d+','one1two2three3four4five5')[1])
print(re.split('\d+','one1two2three3four4five5')[2])
>>>['one', 'two', 'three', 'four', 'five', '']
>>>one
>>>two
>>>three
6. re.sub(pattern, repl, string, count) 在string中查找repl进行替换
subn(pattern, repl, string, count=0, flags=0) 返回替换结果及替换次数
#coding=utf-8
import re
text = "JGood is a handsome boy, he is cool, clever, and so on..."
print(re.sub(r'\s+', '-', text))
print(re.subn(r'\s+', '-', text))
>>> JGood-is-a-handsome-boy,-he-is-cool,-clever,-and-so-on...
>>>('JGood-is-a-handsome-boy,-he-is-cool,-clever,-and-so-on...', 11)