Python 之正则表达式提取数据

实验环境

  • Python 版本:Python 3.6.5

正则表达式

概念

正则表达式就是记录文本规则的代码

特点

  • 正则表达式的语法很令人头疼,可读性差
  • 正则表达式通用行很强,能够适用于很多编程语言


常见语法

字符

语法 说明 表达式案例 完整匹配字符串
一般字符 匹配自身 abc abc
. 匹配任意除换行符\n外的字符(在 DOTALL 模式中也能匹配换行符) a.c abc
|转义字符,使其后一个字符表示字符本身 a.c a.c
[…] 选取字符范围 a[bcd]e abe 或 ace 或 ade

预定义字符集(也可写在字符集 […] 中)

语法 说明 表达式案例 完整匹配字符串
\d 数字:[0-9] a\dc a1c
\D 非数字:[^0-9] a\Dc abc
\s 空白字符:[<空格>\t\r\n\f\v] a\sc a c
\S 非空白字符:[^<空格>\t\r\n\f\v] a\Sc abc
\w 单词字符:[A-Za-z0-9_] a\wc abc
\W 非单词字符:[^A-Za-z0-9_] a\Wc a c

数量词(用在字符或(…)之后)

语法 说明 表达式案例 完整匹配字符串
* 匹配前一个字符0次或无限次 abc* abccc
+ 匹配前一个字符1次或无限次 abc+ abccc
? 匹配前一个字符0次或1次 abc? abc 或 ab
{m} 匹配前一个字符m次 ab{2}c abbc

匹配开头和结尾的正则表达式

语法 功能
^ 匹配字符串开头
$ 匹配字符串结尾

其他

语法 功能
[^指定字符] 表示除了指定字符都匹配

Python 之 re 模块

在 Python 中通过正则表达式提取数据使用的模块为 re

基本用法

# 导入re模块
import re
# 使用match方法进行匹配操作
result = re.match(正则表达式,要匹配的字符串)
# 如果上一步匹配到数据的话,可以使用group方法来提取数据
result.group()

示例:

# coding=utf-8

import re

result = re.match("hello", "hello.cn")
print(result.group())

运行结果为:

匹配单个字符

示例:

# coding=utf-8
import re

ret = re.match(".", "L")
print(ret.group())

ret = re.match("f.y", "fly")
print(ret.group())

ret = re.match("f", "fly to sky")
print(ret.group())

ret = re.match("[Ff]", "fly to sky")
print(ret.group())

ret = re.match("[Ff]ly to sky", "fly to sky")
print(ret.group())

ret = re.match("[0123456789]fly to sky", "1fly to sky")
print(ret.group())

ret = re.match("[0-9]fly to sky", "1fly to sky")
print(ret.group())

ret = re.match("[0-35-9]fly to sky", "1fly to sky")
print(ret.group())

运行结果:

匹配预定义字符集

示例:

# coding=utf-8
import re

ret = re.match("fly2", "fly2sky")
print(ret.group())

ret = re.match("fly\d", "fly2sky")
print(ret.group())

match_obj = re.match("\D", "f")
if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")

match_obj = re.match("fly\sto\ssky", "fly to sky")
if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")

match_obj = re.match("fly\sto\ssky", "fly\tto\tsky")
if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")

match_obj = re.match("fly\Sto\Ssky", "fly-to-sky")
if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")

match_obj = re.match("\w", "A")
if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")

match_obj = re.match("\W", "&")
if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")

运行结果:

匹配多个字符

示例:

# coding=utf-8

import re

ret = re.match("[A-Z][a-z]*", "A")
print(ret.group())

ret = re.match("[A-Z][a-z]*", "AaaA")
print(ret.group())

ret = re.match("[A-Z][a-z]*", "Aab")
print(ret.group())

match_obj = re.match("f.+y", "fly")
if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")

match_obj = re.match("https?", "http")
if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")

ret = re.match("[a-zA-Z0-9_]{6}", "123_abc456_def")
print(ret.group())

ret = re.match("[a-zA-Z0-9_]{8,20}", "123_abc456_def")
print(ret.group())
import re

ret = re.match("[A-Z][a-z]*","M")
print(ret.group())

ret = re.match("[A-Z][a-z]*","MnnM")
print(ret.group())

ret = re.match("[A-Z][a-z]*","Aabcdef")
print(ret.group())

运行结果:

匹配开头和结尾及其他

示例:

# coding=utf-8

import re

# 匹配以数字开头的数据
match_obj = re.match("^\d.*", "1fly")
if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")

# 匹配以数字结尾的数据
match_obj = re.match(".*\d$", "fly1")
if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")

# 匹配以数字开头和结尾的数据
match_obj = re.match("^\d.*\d$", "1fly1")
if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")

# 除了指定字符以外都匹配
match_obj = re.match("[^abcefg]", "d")
if match_obj:
    print(match_obj.group())
else:
    print("匹配失败")

运行结果:

高级匹配

compile 方法

  • 作用:

对正则表达式进行编译构建对象,后续不需要重新构建正则表达式上下文环境,从而提高效率

  • 使用方式:

    # 构建表达式对象
    pattern = re.compile(r'表达式')
    # 通过表达式对象对数据进行操作
    pattern.findall(string)
    

贪婪模式和非贪婪模式

  • 贪婪模式:

(.*) 尽可能多的匹配

  • 非贪婪模式:

(.*?) 一旦匹配到就结束

DOTALL 模式

  • .符号匹配所有的字符包括换行符

  • 使用方法:

    pattern = re.compile(r'表达式', re.DOTALL)
    或
    pattern = re.compile(r'表达式', re.S)
    或
    pattern = re.compile(r'表达式', re.RegexFlag.DOTALL)
    或
    pattern = re.compile(r'表达式', re.RegexFlag.S)
    

忽略大小写模式

  • 正则匹配时忽略大小写

  • 使用方法:

    pattern = re.compile(r'表达式', re.IGNORECASE)
    或
    pattern = re.compile(r'表达式', re.I)
    或
    pattern = re.compile(r'表达式', re.RegexFlag.IGNORECASE)
    或
    pattern = re.compile(r'表达式', re.RegexFlag.I)
    

原始字符串 r 的用法

  • 让字符串内部的转义字符没有任何意义。

四大检索方法

  • match 开头匹配,只匹配一次
  • search 全局匹配,只匹配一次
  • findall 匹配所有符号条件的数据,返回是 结果列表;数据量小使用
  • finditer 迭代对象,迭代 Match 对象;数据量大使用

分组与替换方法

  • split 分组 通过给定字符串进行对数据进行分组
  • sub 替换 通过给定的正则表达式和替换字符进行替换

示例

# coding=utf-8

import re

string = '''
    abcd
    abcd
    abcD
    abcD
'''

# 贪婪匹配
pattern = re.compile(r'a(.*)d')
result = pattern.findall(string)
print(result)

# 非贪婪匹配
pattern = re.compile(r'a(.*?)d')
result = pattern.findall(string)
print(result)

# 贪婪匹配 + DOTALL 模式
pattern = re.compile(r'a(.*)d', re.RegexFlag.S)
result = pattern.findall(string)
print(result)

# 非贪婪匹配 + DOTALL 模式
pattern = re.compile(r'a(.*?)d', re.RegexFlag.S)
result = pattern.findall(string)
print(result)

# 贪婪匹配 + 忽略大小写
pattern = re.compile(r'a(.*)d', re.RegexFlag.IGNORECASE)
result = pattern.findall(string)
print(result)

# 贪婪匹配 + DOTALL 模式 + 忽略大小写
pattern = re.compile(r'a(.*)d', re.RegexFlag.IGNORECASE | re.DOTALL)
result = pattern.findall(string)
print(result)

# 原始字符串 r 的用法
string = r"abc\nd"
pattern = re.compile(r'a(.*)d')
result = pattern.findall(string)
print(result)

# match
string = "123abc"
pattern = re.compile('\d+')
result = pattern.match(string)
print(result.group())

# search
string = "aaa123"
pattern = re.compile('\d+')
result = pattern.search(string)
print(result.group())

string = '''
    abc
    abc
    abc
    abc
'''
pattern = re.compile(r'a(.*)c')
# findall
result = pattern.findall(string)
print(result)

# finditer
results = pattern.finditer(string)
for result in results:
    print(result.group())

# split
string = "ab;c def,gh; i;jk"
pattern = re.compile(r'[; ,]+')
result = pattern.split(string)
print(result)

# sub 交换
string = "key1 value1;key2;key3;key4;key5 value5"
pattern = re.compile(r'(\w+) (\w+)')
result = pattern.sub(r"\2 \1", string)
print(result)

运行结果: