正则表达式(RegularExpression, re)

  • 是一个计算机科学的概念
  • 用于使用单个字符串来描述,匹配一系列匹配某个句法规则的字符串
  • 常用来检索,替换某些模式的文本

正则表达式的写法

  • .(点号): 匹配任意一个字符,除了 \n
  • []: 匹配中括号中列举的字符,例如[LY]
  • \d: 表示任意一个数字,0-9
  • \D: 表示非数字,即不是数字就可以
  • \s: 匹配空白,即空格,tab键
  • \S: 除了空白以外的字符
  • \w: 单词字符,即a-z, A-Z, 0-9, _
  • \W: 非单词字符
  • *: 表示前面内容重复零次或者多次
  • +: 前面内容重复至少一次
  • ?: 前面出现的内容零次或者一次
  • {m,n}: 允许前面内容出现最少m次,最多n次
  • ^: 匹配字符串的开始
  • $: 匹配字符串的结尾
  • \b: 匹配单词的边界
  • (): 对正则表达式内容进行分组,从第一个括号开始,编号逐渐增大

示例:

# 验证一个数字
^\d$

# 必须有一个数字,最少一位
^\d+$

# 只能出现数字,且位数为5-10位
^\d{5,10}$

# 注册者输入年龄,要求16岁以上,99岁以下
^[1-9][0-9]$

# 只能输入英文字符和数字
^[A-Za-z0-9]+$

# 验证QQ号码
^[1-9][0-9]{4,11}$
  • \A: 只匹配字符串开头,\Aabcd,则abcd
  • \Z: 仅匹配字符串末尾,abcd\Z,abcd
  • |: 左右任意一个
  • (?P<name>...): 分组,除了原来的编号再制定一个别名,(?P<id>12345){2},1234512345
  • (?P=name): 引用分组

re 模块

  • re.match(re_exp): 从开始查看是否能跟定义的正则相匹配
  • result.group: 如果匹配数据成功,可以使用group来提取数据
  • 案例01, 案例代码是以函数进行区分,每个函数对应某个知识点,看下面的知识点对应具体函数理解就好
import re

def fun_1():
    s = "I love wangxiaojing"

    # 匹配是否跟wangxiaojing表白过
    rst = re.match("wangxiaojing love", "wangxiaojing love me")

    r = rst.group()
    print(type(r))
    print(r)


def fun_2():
    # 匹配任意一个字符
    rst = re.match(".", "9")
    print(rst.group())

    rst = re.match(".", "B")
    print(rst.group())

    rst = re.match("w", "Wang")
    # 匹配为空
    # print(rst.group())

    rst = re.match("[wW]", "wang")
    print(rst.group())

    rst = re.match("[0123456789]", "89years")
    print(rst.group())

    # 匹配两位数字或者一位数字
    rst = re.match("[0123456789]{1,2}", "89years")
    print(rst.group())

    # 匹配至少一位数字
    rst = re.match("[0123456789]+", "809years")
    print(rst.group())


def fun_3():
    '''匹配字符'''
    rst = re.match("[i]+", "i love wangxiaojing")
    print(rst.group())

    rst = re.match("\w+", "i love 3th wangxiaojing")
    print(rst.group())


def fun_4():
    dir = "C:\\a\\b\\c.txt"
    print("DIR={0}".format(dir))

    rst = re.match("C:\\\\a", dir)
    print(rst.group())

    rst = re.match(r"C:\\a", dir)
    print(rst.group())


def fun_5():
    rst = re.match("[1-9]?\d", "9")
    print(rst.group())

    rst = re.match("[1-9]?\d", "19")
    print(rst.group())

    rst = re.match("[1-9]?\d", "09")
    print(rst.group())

    rst = re.match("[1-9]?\d$", "09")
    # 匹配为空
    # print(rst.group())

    rst = re.match("[1-9]?\d|\d+$", "09")
    print(rst.group())

    rst = re.match("[1-9]?\d$|\d+$", "09")
    print(rst.group())

    # 匹配邮箱
    rst = re.match("\w{4,30}@163\.com", "wangdapeng@163.com")
    print(rst.group())

    # 匹配邮箱
    rst = re.match("\w{4,30}@(163|126|qq)\.com", "wangdapeng@126.com")
    print(rst.group())


def fun_6():
    s = "i love wangxiaojing and zhangmingmin and lihua"
    # search查找的结果只能是一个
    rst = re.search("o", s)
    print(rst.group())

    rst = re.findall("[oi]", s)
    print(type(rst))
    print(rst)

    rst = re.sub("[oi]", "8", s)
    print(type(rst))
    print(rst)
    print(s)


fun_6()

re中原生字符串问题

  • 字符串中会包含转义字符
  • 在re中,转义字符会带来一些麻烦,能不能尽量减少转义字符的出现
  • 在字符串前使用r字符,表示后面字符串是原始字符串,不需要转义,例如 r'c:\wk\readme.txt'
  • 案例01-fun_4

正则的分组表示

  • |: 匹配左右任意一个表达式
  • (ab): 将括号中字符作为一个分组
  • \num: 引用分组num匹配到的字符串
  • (?P<name>): 分组起一个别名,其中P是大写
  • (?P=name): 引用别名为name分组匹配到的字符串
  • 案例01中 fun_5函数

re 模块的一般使用步骤如下:

  1. 使用 compile() 函数将正则表达式的字符串形式编译为一个 Pattern 对象
  2. 通过 Pattern 对象提供的一系列方法对文本进行匹配查找,获得匹配结果,一个 Match 对象
  3. 最后使用 Match 对象提供的属性和方法获得信息,根据需要进行其他的操作

re常用函数

  • group([group1, …]) 方法用于获得一个或多个分组匹配的字符串,当要获得整个匹配的子串时,可直接使用 group()group(0)
  • start([group]) 方法用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0
  • end([group]) 方法用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引 +1),参数默认值为 0
  • span([group]) 方法返回 (start(group), end(group))

正则的其他用法

  • 案例01, fun_6
  • search: 查找其中一个内容
  • findall: 查找所有内容
  • sub: 查找替换,返回替换之后的内容,原来被替换的内容不变

匹配代码

import re

p = re.compile(r'\d+')
m = p.match("one12twothree34four")
print(m)

m = p.match("one12twothree34four", 3, 10)
print(m)
print(m[0])

m.start(0)  # 参数是组号
m.end(0)

# 第二个例子
p = re.compile(r'([a-z]+) ([a-z]+)', re.I)  # re.I表示忽略大小写,两个中间有空格
m = p.match('I really love wangxiaojing ')
print(m)
print(m.group(0))
m.start(0)
m.span(0)
m.group(1)
m.group(2)
m.group(0)  # 整个匹配子串
m.groups()  # 全部的打印出来

查找代码

  • search(str[, pos[, endpos]])
  • findall
  • finditer
import re

p = re.compile(r'\d+')
m = p.search('one12twothree34four')
print(m.group())

p = re.compile('\d+')
m = p.search('hello 123456 7890')
print(m.group())

# findall
rst = p.findall("hello 12345 67890")
print(rst)

sub替换

  • sub(rep1, str[,count])
import re

p = re.compile(r'(\w+) (\w+)')  # \w是字符
s = "hello 123 and hello 456"

rst = p.sub(r'hello world', s)
print(rst)

rst = p.sub(r'\2 \1', s)
print(rst)

def func(m):
    return 'gaga' + m.group(2)

rst = p.sub(func, s)
print(rst)

rst = p.sub(func, s, 1)
print(rst)

匹配中文

  • 中文主要表示范围是 [\u4e00-\u9fa5],不包括全角标点
import re

title = u'你好 世界, hello moto'
p = re.compile(r'[\u4e00-\u9fa5]+')
rst = p.findall(title)
print(rst)

贪婪和非贪婪

  • 尽可能多的匹配,*
  • 非贪婪,?
  • 默认贪婪
import re

title = u'<div>name</div><div>age</div>'

p1 = re.compile(r"<div>.*</div>")
p2 = re.compile(r"<div>.*?</div>")

m1 = p1.search(title)
print(m1.group())

m2 = p2.search(title)
print(m2.group())

This site uses Just the Docs, a documentation theme for Jekyll.