第十四天:正则表达式

一、概述

1、概念

  • Regular Expression
  • 一种文本模式,描述在搜索文本时要匹配的一个或多个字符串
    正则表达式(regular expression)描述了一种字符串匹配的模式(pattern),可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。

2、典型场景

  • 数据验证
  • 文本扫描
  • 文本提取
  • 文本替换
  • 文本分割

3、语法

字面值

普通字符

需转义

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

元字符

4、匹配

单字,预定义元字符

  • 除\n外的所有字符 .
  • 数字,等同于[0-9] \d
  • 非数字,等同于[^0-9] \D
  • 空白字符 [\t \n \r \f \v] \s
  • 非空白字符 [^\t \n \r \f \v] \S
  • 字母数字字符 [a-z A-Z 0-9 _ ] \w
  • 非字母数字字符 [^a-z A-Z 0-9 _ ] \W

批量备选 或( | ) , 如yes|no

量词(控制 "字符、元字符,字符集" 如何重复)

  • 0或1次 ?
  • 0次或多次 *
  • 1次或多次 +
  • 特定
    • 范围次数
    • n次
    • 至少n次
    • 至多m次

贪婪与非贪婪

贪婪(默认):尽量匹配最大范围结果

非贪婪:尽量匹配最小的范围结果

  • 方法:量词后追加?
  • 例子
    • ??
    • *?
    • +?

边界匹配

  • 行首 ^
  • 行尾 $
  • 单词边界 \b
  • 非单词边界 \B
  • 输入的开头 \A
  • 输入的结尾 \Z
  • 注:可能会由于上下文不同而有所差异

二、Python 正则

模块

  • import re

RegexObject 正则对象

1、模式对象,表现编译后的正则表达式(编译为字节码并缓存)

2、编译

  • re.compile(r'模式')

3、.findall()

  • 查找所有非重叠匹配项
  • 返回list
import re
text = "Tom is 8 years old. Mike is 34 years old."
pattern = re.compile('\d+') #数字,等同于[0-9]  \d,1次或多次 +
pattern.findall(text) #开发的方法
re.findall('\d+', text) #这种实现也可以,实际开发常用第一种,后面的参数是指明在哪寻找
['8', '34']
['8', '34']
import re
s = '\\author:Tom'
pattern = re.compile('\\\\author') #第一种查找有转义符的方式
pattern.findall(s)
pattern = re.compile(r'\\author')#第二种查找转义符的方式
pattern.findall(s)
['\\author']
['\\author']

4、.match(string[,pos[,endpos]])

  • 匹配,仅从起始位置
  • 返回MatchObject
import re
text = 'Tom is 8 years old. Mike is 34 years old.Peter is 87 years old.'
p_name = re.compile(r'[A-Z]\w+') #字母数字字符 [a-z A-Z 0-9 _ ] \w,1次或多次 +
p_name.findall(text)
['Tom', 'Mike', 'Peter']
import re
pattern = re.compile(r'<html>')
text = '<html><head></head><body></body></html>'
pattern.match(text) #返回MatchObject对象
text2 = ' <html><head></head><body></body></html>'
pattern.match(text2, 1) #match只从开始的位置开始匹配,字符串前面有空格就不行,返回空,要设置了\开始匹配的位置,就能顺利返回查找对象
<re.Match object; span=(0, 6), match='<html>'>
<re.Match object; span=(1, 7), match='<html>'>

5、.search(string[,[pos[,endpos]]])

  • 任意位置搜索
  • 返回 MatchObject
text2 = ' <html><head></head><body></body></html>'
pattern.search(text2) #不管什么位置都能查找
<re.Match object; span=(1, 7), match='<html>'>
import re
text = 'Tom is 8 years old. Mike is 34 years old.Peter is 87 years old.'
p1 = re.compile(r'\d+')
p2 = re.compile(r'[A-Z]\w+')
it = p1.finditer(text)
for m in it:
    print(m) #返回每个查找到对象的起始与终止,还有对象
<re.Match object; span=(7, 8), match='8'>
<re.Match object; span=(28, 30), match='34'>
<re.Match object; span=(50, 52), match='87'>

MatchObject 匹配对象

1、表现被匹配的对象

2、 .group()

  • 参数为0或空返回整个匹配
  • 有参时返回特定分组匹配细节
  • 参数也可以是分组名称
import re
text = 'Tom is 8 years old. Jerry is 34 years old.'
pattern = re.compile(r'(\d+).*?(\d+)')
m = pattern.search(text)
m.group()
m.group(1) #方法里面的参数,0表示整体,1表示第一个对象,2表示第二个对象
'8 years old. Jerry is 34'
'8'
import re
pattern = re.compile(r'(\w+) (\w+)') #注意中间有空格
text = 'Beautiful is better than ugly.'
it = pattern.finditer(text)
for m in it:
    print(m.group())
Beautiful is
better than

3、.groups()

  • 返回包含所有子分组的元组
m.groups()
('8', '34')

4、.start()

  • 返回特定分组的起始索引
m.start(1) #返回找到的第一个对象在元字符串的索引下标
7

5、.end()

  • 返回特定分组的终止索引
m.end(1) #返回查到的第一个对象终止的下标,在这里也就是数字8后面的空格的索引
8

6、.span()

  • 返回特定分组的起止索引元组

7、.groupdict()

  • 以字典表形式返回分组名及结果

Group 编组

1、场景

  • 从匹配模式中提取信息
  • 创建子正则表达式以应用量词
import re
re.search(r'ab+c', 'ababc')
re.search(r'(ab)+c', 'ababc')
<re.Match object; span=(2, 5), match='abc'>
<re.Match object; span=(0, 5), match='ababc'>
  • 限制备选项范围
re.search(r'Center|re', 'Center')
re.search(r'Center|re', 'Centre')
re.search(r'Cent(er|re)', 'Centre')
re.search(r'Cent(er|re)', 'Center')
<re.Match object; span=(0, 6), match='Center'>
<re.Match object; span=(4, 6), match='re'>
<re.Match object; span=(0, 6), match='Centre'>
<re.Match object; span=(0, 6), match='Center'>
  • 重用正则模式中提取的内容
re.search(r'(\w+) \1', 'hello hello worlds')
import re
text = "Tom:98"
pattern = re.compile(r'(\w+):(\d+)')
m = pattern.search(text)
m.group()
m.groups()
m.group(1)
'Tom:98'
('Tom', '98')
'Tom'

2、声明

  • (模式)
  • (?P模式)

3、引用

  • 匹配对象内 m.group(‘name’)
  • 模式内 (?P=name)
  • 表现内 \g
pattern = re.compile(r'(?P<name>\w+):(?P<score>\d+)')
m = pattern.search(text)
m.group()
m.group('name')
m.group('score')
'Tom:98'
'Tom'
'98'

应用

1、字符串操作

  • .split(string,maxsplit=0)
    分割字符串,使用编组不会删除分割内容
import re
text = 'Beautiful is better ugly.\nExplicit is better than implicit.\nSimple is better than complex.'
p = re.compile(r'\n')
p.split(text)
re.split(r'\n', text, 1)
['Beautiful is better ugly.',
 'Explicit is better than implicit.',
 'Simple is better than complex.']
['Beautiful is better ugly.',
 'Explicit is better than implicit.\nSimple is better than complex.']
  • .sub(repl,string,count=0)
    替换字符串
import re
ords = 'ORD000\nORD001\nORD003'
re.sub(r"\d+",'-', ords)
text = 'Beautiful is *better* ugly.'
re.sub(r'\*(.*?)\*','<strong>\g<1></strong>', text)
re.sub(r'\*(?P<html>.*?)\*','<strong>\g<html></strong>', text) #也可以使用这种方法
re.sub(r'([A-Z]+)(\d+)','\g<2>-\g<1>', ords)
'ORD-\nORD-\nORD-'
'Beautiful is <strong>better</strong> ugly.'
'Beautiful is <strong>better</strong> ugly.'
'000-ORD\n001-ORD\n003-ORD'
  • .subn(repl,string,count=0)
    替换并返回替换数量
re.subn(r'([A-Z]+)(\d+)','\g<2>-\g<1>', ords)
('000-ORD\n001-ORD\n003-ORD', 3)

2、编译标记

  • 改变正则的默认行为
  • 忽略大小写 re.I
import re
text = 'Python python PYTHON'
re.search(r'python', text)
re.findall(r'python', text, re.I) #忽略大小写
['Python', 'python', 'PYTHON']
  • 忽略多行 re.M
import re
re.findall(r'^<html>', '\n<html>', re.M)
['<html>']
  • 指定“.”匹配所有字符包括\n re.S
re.findall(r'\d(.)','1\ne',re.S)
['\n']

3、模块级别操作

  • 清理正则缓存 re.purge()
  • 逃逸字符 re.escape()
posted @ 2019-09-10 21:07  败家小林  阅读(419)  评论(0编辑  收藏  举报