Python-正则(regex)

即文本的高级匹配模式,提供搜索,替代等功能。其本质是一系列由特殊符号组成的字串,这个字串即正则表达式。
由普通字符和特殊符号组成字符串,通过描述字符的重复和位置等行为,达到匹配某一类字符串的目的

概述

动机

  1. 文本处理已经成为计算机的常见工作之一
  2. 对文本内容的搜索,定位,提取是逻辑比较复杂的工作
  3. 为了快速解决上述问题,产生了正则表达式技术

定义

即文本的高级匹配模式,提供搜索,替代等功能。其本质是一系列由特殊符号组成的字串,这个字串即正则表达式。

匹配原理

由普通字符和特殊符号组成字符串,通过描述字符的重复和位置等行为,达到匹配某一类字符串的目的

目标

  1. 熟练掌握正则表达式符号
  2. 实现基本的文本搜索,定位,提取,理解正则用法
  3. 能够适用re模块操作正则表达式

特点

  • 方便文本处理
  • 支持语言众多
  • 使用灵活多样

基础实践

re模块简单实用

1
re.findall(pattern, string)

功能: 使用正则表达式匹配目标字符串内容
参数

  • pattern 正则表达式
  • string 目标字符串
    返回值: 列表,列表中为匹配到的内容

元字符的使用

普通字符

元字符a b c
匹配规则: 每个字符匹配对应的字符

1
2
re.findall("hello","hello world")
['hello']
1
2
re.findall("你好","你好北京")
['你好']

元字符|
匹配规则: 匹配 | 两边任意一个正则表达式

1
2
re.findall("ab|cd","abcdefghialkjasbab")
['ab', 'cd', 'ab']

匹配单个字符

元字符.
匹配规则: 匹配除换行外的任意字符

1
f.o --> foo  fao  f@o  f o
1
2
re.findall("f.o","foo is not fao")
['foo', 'fao']

匹配开始位置

元字符^
匹配规则:匹配目标字符串的开头位置

1
2
re.findall("^Tom","Tom is a boy")
['Tom']

匹配结束位置

元字符$
匹配规则 : 匹配字符串的结束位置

1
2
re.findall("Tom$","hi Tom")
['Tom']

匹配重复 *

元字符*
匹配规则: 匹配前面的字符出现0次或多次

1
fo*  --> fooooooooo  f  fo
1
2
re.findall("fo*","fadsfafoooafo")
['f', 'f', 'fooo', 'fo']

匹配重复 +

元字符+
匹配规则: 匹配前面的字符出现1次或多次

1
fo+  --> fo   fooooo
1
2
re.findall("fo+","fadsfafoooafo")
['fooo', 'fo']

匹配重复 ?

元字符?
匹配规则: 匹配前面的字符出现0次或1次

1
fo? -->  f   fo
1
2
re.findall("fo?","fasdffoafooooo")
['f', 'f', 'fo', 'fo']

匹配重复 {n}

元字符{n}
匹配规则: 匹配指定的重复次数

1
fo{3}  --> fooo
1
2
re.findall("fo{2}","fasdffoafooooo")
['foo']

匹配重复 {m,n}

元字符{m,n}
匹配规则 : 匹配前面的正则表达式 m–n次

1
fo{2,4} --> foo  fooo  foooo
1
2
re.findall("fo{2,4}","fasdfofoooafooooo")
['fooo', 'foooo']

匹配字符集合

元字符[字符集]
匹配规则 : 匹配任意一个字符集中的字符

1
2
3
4
5
[abc123]   a  b  c  1  2  3 
[a-z]
[A-Z]
[0-9]
[_123a-z]
1
2
re.findall("^[A-Z][a-z]*","Boy")
['Boy']

匹配字符集

元字符[^...]
匹配规则 :字符集取非,除列出的字符之外任意一个字符

1
[^abc] --> 除a b c之外任意字符
1
2
re.findall("[^ ]+","a little boy")
['a', 'little', 'boy']

匹配任意(非)数字字符

元字符\d \D
匹配规则

  • \d 匹配任意数字字符 [0-9]
  • \D 匹配任意非数字字符 [^0-9]
1
2
re.findall("1\d{10}","18888886666")
['18888886666']

匹配任意(非)普通字符

元字符\w \W
匹配规则:

  • \w 普通字符 [_0-9a-zA-Z] 也能匹配普通汉字
  • \W 非普通字符
1
2
re.findall("\w+","hello#nihao%asdf@adsgdfg!df&")
['hello', 'nihao', 'asdf', 'adsgdfg', 'df']
1
2
re.findall("\W+","hello#nihao%asdf@adsgdfg!df&")
['#', '%', '@', '!', '&']

匹配任意(非)空字符

元字符

  • \s 匹配任意空字符 [ \r\t\n\v\f]
  • \S 匹配任意非空字符
1
2
re.findall("\w+\s+\w+","hello   world")
['hello world']
1
2
re.findall("\S+","hello this is tom")
['hello', 'this', 'is', 'tom']

空格也属于空字符

匹配字符串位置

元字符\A \Z
匹配规则

  • \A 匹配字符串开头位置 ^
  • \Z 匹配字符串结尾位置 $

绝对匹配 : 正则表达式要完全匹配目标字符串内容

在正则表达式开始和结束位置加上^ $ (或者\A \Z)。这样正则表达式必须匹配整个目标字符串才会有结果

1
2
re.findall("\A\d+\Z","123445")
['123445']

匹配(非)单词边界

元字符\b \B
匹配规则

  • \b 匹配单词边界位置 普通字符和非普通字符交界认为是单词边界
  • \B 匹配非单词边界位置
1
2
re.findall(r"num\b","num#asdf#")
['num']
1
2
re.findall(r"num\b","numasdf#")
[]

元字符总结

匹配单个字符 : a . \d \D \w \W \s \S [...] [^...]

匹配重复 : * + ? {n} {m,n}

匹配位置 : ^ $ \A \Z \b \B

其他 : | () \

正则表达式转义

正则中的特殊符号:

. * + ? ^ $ [] {} () | \

正则表达式如果匹配特殊字符需要加 \ 表达转义

1
2
	 正则          目标字符串
e.g. \$\d+ ----> $10
1
2
3
4
         pattern        string
python "\\$\\d+" "$10"

raw r"\$\d+" "$10"

raw字串 : 原始字符串对内容不解释转义,就表达内容原 本意义

贪婪与非贪婪

贪婪模式 : 正则表达式的重复匹配总是尽可能多的向后匹配更多内容

* + ? {m,n}

非贪婪(懒惰模式) : 尽可能少的匹配内容

贪婪 —> 非贪婪 *? +? ?? {m,n}?

1
2
re.findall(r"ab+?","abbbbbbbb")
['ab']
1
2
re.findall(r"ab??","abbbbbbbb")
['a']

正则表达式的子组

可以使用()为正则表达式建立子组,子组可以看做是正则表达式内部操作的一个整体

子组是在正则表达式整体匹配到内容的前提下才会发挥作用,它不影响正则表达式整体去匹配目标内容这一原则

子组使用
  1. 作为内部整体可以改变某些元字符的行为
1
2
re.search(r"(ab)+\d+","ababab1234").group()
'ababab1234'
1
2
re.search(r"\w+@\w+\.(com|cn)","abc@123.com").group()
'abc@123.com'
  1. 子组在某些操作中可以单独提取出匹配内容
1
2
re.search(r"(https|http|ftp)://\S+","https://www.baidu.com").group(1)
'https'
子组使用注意事项
  • 一个正则表达式中可以有多个子组
  • 子组一般由外到内,由左到右称之为第一,第二 第三。。。。子组
  • 子组不能重叠,嵌套也不宜很多

search 只能匹配一个结果

捕获组 和 非捕获组

1
格式 : (?P<name>pattern)
1
2
3
e.g.
re.search(r"(?P<dog>ab)cdef",'abcdefghti').group('dog')
Out[130]: 'ab'

作用 : 可以通过组名更方便获取某组内容

正则表达式设计原则

  1. 正确性 ,能正确匹配到目标内容
  2. 排他性 ,除了要匹配的内容,尽可能不会匹配与到其他内容
  3. 全面性 ,需要对目标的各种情况进行考虑,做到不遗漏

re模块

compile

用来生成正则表达式对象

regex = compile(pattern,flags=0)

  • 功能 : 生成正则表达式对象
  • 参数 :
    • pattern 正则表达式
    • flags 功能标志位,丰富正则表达式的匹配功能
  • 返回值 : 返回正则表达式对象

findall

re模块调用

re.findall(pattern,string,flags)

  • 功能 :从目标字符串查找正则匹配内容
  • 参数 :
    • pattern 正则表达式
    • string 目标字符串
    • flags 标志位
  • 返回值 : 返回匹配到的内容 如果正则有子组则只返回子组对应内容

正则对象调用

regex.findall(string,pos,endpos)

  • 功能 :从目标字符串查找正则匹配内容
  • 参数 :
    • string 目标字符串
    • pos 匹配目标的起始位置
    • endpos 匹配目标的终止位置
  • 返回值 : 返回匹配到的内容 如果正则有子组则只返回子组对应内容

split

正则表达式所匹配的内容,做字符串的切割
re.split(pattern,string,flags = 0)

  • 功能:根据正则匹配内容切割字符串
  • 参数: pattern string flags
  • 返回值: 返回列表,列表中为切割的内容

sub

使用一个字符串去替换目标字符串被正则表达式匹配到的内容
re.sub(pattern,replaceStr,string,max,flags)

  • 功能: 替换正则匹配到的目标子串部分
  • 参数:
    • pattern
    • replaceStr : 要替换的内容
    • string
    • max 最多替换几处 默认全部替换
    • flags
  • 返回值 : 返回替换后的字符串

subn

使用一个字符串去替换目标字符串被正则表达式匹配到的内容
re.subn(pattern,replaceStr,string,max,flags)

  • 功能: 替换正则匹配到的目标子串部分
  • 参数:
    • pattern
    • replaceStr : 要替换的内容
    • string
    • max 最多替换几处 默认全部替换
    • flags
  • 返回值 : 返回一个元组,为实际替换了几处和替换后的字符串

sub 和 subn区别

  • sub返回替换后的字符串
  • subn返回替换了几处

finditer

相比findall返回一个迭代对象
re.finditer(pattern,string,flags)

  • 功能: 使用正则表达式匹配目标字符串
  • 参数: pattern string flags
  • 返回值: 返回一个迭代对象,迭代到的内容是一个match对象

fullmatch

相当于在最前面写一个^,最后面写一个$, 只匹配到一处,返回一个match对象
fullmatch(pattern,string,flags)

  • 功能: 完全匹配目标字符串
  • 参数: pattern,string,flags
  • 返回值:返回匹配到的match对象 如果没匹配成功返回None

match

相当于只匹配到开头,返回一个match对象
match(pattern,string,flags)

  • 功能: 从开头位置匹配目标字符串
  • 参数: pattern,string,flags
  • 返回值:返回匹配到的match对象 如果没匹配成功返回None

search(pattern,string,flags)

  • 功能: 正则表达式匹配目标字符串,只匹配第一处
  • 参数: pattern,string,flags
  • 返回值:返回匹配到的match对象 如果没匹配成功返回None

compile对象属性:

flags : 标志位
pattern : 正则表达式
groups: 有多少子组
groupindex : 捕获组形成组名和序列号的字典
组名为键,第几组为值

match对象属性

属性变量

1
2
3
4
5
6
pos     匹配目标字符串的开始位置
endpos 匹配目标字符串的结束位置
re 正则表达式
string 目标字符串
lastgroup 最后一组的组名
lastindex 最后一组是第几组

属性方法

1
2
3
span()  匹配内容的开始位置
start() 匹配内容的结束位置
end() 匹配内容的起止位置
1
2
3
4
5
group()
功能 : 获取match对象对应的内容
参数 : 默认为0 表示获取整个正则匹配的内容
如果为序列号或者子组名则为获取某个子组匹配的对应内容
返回值:返回得到的子串
1
2
groupdict()  获取捕获组名作为键,对应内容作为值的字典
groups() 获取每个子组匹配内容

flags 参数的使用

re.compile re.findall re.search re.match
re.finditer re.fullmatch re.sub re.subn re.split
上面这些方法都有flags参数
作用: 辅助正则表达式,丰富匹配结果

1
2
3
4
I ==  IGNORECASE  匹配时忽略字母的大小写
S == DOTALL 作用于元字符 . 使其可以匹配换行
M == MULTILINE 作用于^ $ 使其可以匹配每一行开头结尾位置
X == VERBOSE 可以给正则添加注释

使用多个标志位使用按位或连接

1
2
e.g.
flags = re.X | re.I