文本处理中正则表达式基础

前言

正则表达式可以在文本处理和文本清洗中发挥巨大的作用,有时候能够承担起一部分的信息提取工作。

基础符号

符号 作用 解释 记忆
^ 匹配开头 ^a表示匹配以a开头的字符串 -
$ 匹配结尾 a$表示匹配以a结尾的字符串 买完菜东西就要付钱
? 匹配0次或1次 a?表示匹配a0次或者1次 你到底有没有青菜卖?
* 匹配0次或无数次 a*表示匹配a0次或者无数次 我比较有钱,没有青菜就算了,如果有多少我要多少,多给你几倍钱
+ 匹配1次或无数次 a+表示匹配a1次或者无数次 只要你有青菜,我就多加几颗
\n 匹配换行 - -
\s 匹配任意空白字符 相当于\t、\n、\r、\f这些 space,空格
\S 匹配任意非空白字符 - 小的不要的我都要
\d 匹配阿拉伯数字 匹配0-9这十个阿拉伯数字 digit,数字
\D 匹配任意非数字 - 小的不要的我都要
\w 匹配字母数字及下划线 相当于匹配数字0-9、大小字母a-zA-Z还有下划线 (我的)word账号只支持字母数字和下划线
\W 匹配非字母数字及下划线 - 大的不要的我都要
[\u4e00-\u9fa5] 匹配中文 - 很难记住,要用就去查
{} 一般用在限定匹配次数 a{1,}表示匹配a1次以上,相当于+;a{2,7}表示匹配a2到7次;a{6}表示匹配a6次 我比问号、加号、乘号都厉害
[] 出现在这个中括号里面的字符都会被单个匹配 [abc]匹配a,b或者c 疫情紧张,超市限购,青菜每个人只能买一颗
[^] 出现在这个中括号里面^后面字符都不会被单个匹配 [^abc]不匹配a,b或者c 超市还没开门,开头来的几个人都没买到菜
| 满足多个正则表达式 a|b|c表示匹配a或者b或者c,不同于[],|可以匹配字符串或者满足不同正则的字符串 有多个表达式或者要匹配多个字符串就找我,我比[]强大

寻找

re.match

功能描述: 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。

import re

text = '时间:2020年6月22日'
if re.match(r'[时间日期]{0,2}[::]?', text):
print('这句话以日期标示开头')

re.match(r’abc’)相当于re.search(r’^abc’)

功能描述: 扫描整个字符串并返回第一个成功的匹配,它可以用来判定每个表达式满足的字符串是否在文本中。

import re

# 列子一,把下列的生日标示都匹配出来
list_1 = ['出生年月:1992.3.19', '生日:1992.3.19', '出生日期:1992.3.19', '生日 92.03.19']
print([item for item in list_1 if re.search(r'[出生]{1,2}[日年][月期]?[::]?', item)])
import re

# 列子二,把下列的电话号码都匹配出来
list_2 = ['18826229080', '188-2622-9080', '188-26229080', '86-18826229080', '188--2622--9080']
print([item for item in list_2 if re.search(r'(86)?[-]*1[3-9]\d[-]*\d{4}[-]*\d{4}', item)])
import re

# 列子三,把下列元素都匹配出来
list_3 = ['工作经验', '工作履历', '【工作经验】', '「工作经验」', '工作背景']
print([item for item in list_3 if re.search(r'[「【]?工作[经履][历验][】」]?[::]?[\n\s]?|工作背景[\n\s]?', item)])

提取

re.findall

功能描述: 在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。

import re

string = 'abcdefg acbdgef abcdgfe cadbgfe'

# 带括号与不带括号的区别

# 带括号可以限定提取的内容
print(re.findall(r'((\w+)\s+\w+)', string))
# 输出:[('abcdefg acbdgef', 'abcdefg'), ('abcdgfe cadbgfe', 'abcdgfe')]

print(re.findall(r'(\w+)\s+\w+', string))
# 输出:['abcdefg', 'abcdgfe']

# 不带括号
print(re.findall(r'\w+\s+\w+', string))
# 输出:['abcdefg acbdgef', 'abcdgfe cadbgfe']

re.search

功能描述: 扫描整个字符串并返回第一个成功的匹配。

import re

# 使用group获取匹配到的字符串
print(re.search(r'广州', '我在广州读书,然后在广州工作').group())
# 输出:广州

# 使用span获取匹配到的首位位置
print(re.search(r'广州', '我在广州读书,然后在广州工作').span())
# 输出:(2, 4)

re.finditer

功能描述: 他可以看作是对re.search的补充,通过re.search只能获取到第一个成功的匹配,但是它可以获取到所有的成功的匹配。

import re

def extract_time_period(text):
"""
日期段的抽取正则
:param text:
:param segment:
:return:
"""
date_regex = r'[1,2][0,9]\d{2}[/年\-–-—.]([0-1]?\d月?([/\-–-—.][0-3]?\d日?)?)?'
hyphen_regex = r'[—―–-­\-\~~到]{1,2}[至今现在]{0,2}'
period_regex = date_regex + hyphen_regex + date_regex + r'|' + date_regex + hyphen_regex
dates = re.finditer(period_regex, text, re.DOTALL)
return [date.group() for date in dates if dates is not None]

text = '2019年3月-2020年3月,2019年3月~2020年3月,2019年3月~至今,1992.3.19--2000.3.19,2020/03/11~2021/05/22'

print(extract_time_period(text))

# 输出:['2019年3月-2020年3月', '2019年3月~2020年3月', '2019年3月~至今', '1992.3.19--2000.3.19', '2020/03/11~2021/05/22']

替换

replace

它的局限在于你无法使用正则。

re.sub

功能描述: 用于替换字符串中的匹配项。

# 和replace一样的用法
print(re.sub(r'abc', '贤', '我是abc'))
# 输出:我是贤
# 消除逗号两边的空格
print(re.sub(r'\s*,\s*', ',', '我 , 是贤'))
# 输出:我,是贤
# 带有占位符的使用方法1:去除重复的标点
print(re.sub(r'(,){2,}', r'\1', '我,,,是首贤'))
# 输出:我,是首贤

# 带有占位符的使用方法2:消除中英文的双重叠字
print(re.sub(r'([a-zA-Z\u4e00-\u9fcc])\1{1,2}', r'\1', '我我是是首首贤贤aabbcc'))
# 输出:我是首贤abc

分割

split

它的局限在于你无法使用正则。

re.split

功能描述: 按照能够匹配的子串将字符串分割后返回列表。

# 和splite一样的用法
print(re.split(' ', 'hello world'))
# 输出:['hello', 'world']

# 通过正则分割
print(re.split('\W+', '我,是,首贤'))
# 输出:['我', '是', '首贤']

# 对于一个找不到匹配的字符串而言,split 不会对其作出分割
print(re.split(r'a+', 'hello world'))
# 输出:['hello world']

更多操作

相关参数

# re.I 忽略英文大小写
print(re.search(r'qq', 'QQ', re.I))
text = '我是首贤  \n \
我来自地球'

# re.S(re.DOTALL)参数用作跨行匹
print(re.findall(r'我', text, re.S))

综合利用

import re

# 去掉行内空格

text = '我 是 首贤 \n \
我来 自 地球 '

content_list = re.split(r'\n', text)
content_list = [re.sub(r'\s', '', line) for line in content_list if line != '']
content = '\n'.join(content_list)
print(content)

# 输出:
# 我是首贤
# 我来自地球
文章作者: Stanleylsx
文章链接: http://yoursite.com/2020/06/11/%E6%96%87%E6%9C%AC%E5%A4%84%E7%90%86%E4%B8%AD%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%9F%BA%E7%A1%80/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 LSXのBlog