Py学习  »  Python

动手学正则表达式(含Python代码实践)

AINLP • 3 年前 • 339 次点击  


「背景前情提要」

学好偏导竟能追到心仪的妹子

💘背景

“什么?你快得手了!恭喜恭喜!”

“还在暧昧期了啦,嘿嘿”

“那你今天为啥又找我?(躲避脸)”

“没事,没事,真的!大佬先坐一坐。”

“感觉不对呀!(准备起身离开这险恶的环境了)”

“就是有个问题了,你不会眼看着我在近在咫尺的成功面前败下来吧?”

“真是城会玩!行吧,你说咯。(嫌弃脸)”

“你说我准备饭后给她点个🍮,合理吧,于是我就问她的地址,这合理吧”

“你想说什么?!”

“到了到了,哈哈,点外卖总得知道电话,这很合理吧,不过她给我发了一堆文字(见上图),说从里面找出她的电话☎️,你想我这个学渣,怎么看得懂?大佬救命,完事后,海底捞来一顿!”

“看在你这么有诚意的份上,行吧,下不为例!(感觉是不太可能了)”

正则表达式

「本文将从简单到容易,通过🌰解释常用的正则表达式的用法。全文分为以下几部分:」

  1. python库函数
  2. 匹配单个字符
  3. 匹配多个字符
  4. 元字符
  5. 重复字符串匹配
  6. 位置匹配
  7. 使用子表达式
  8. 使用回溯
  9. 前后查找
  10. 嵌入条件

0. python库函数

常用的正则表达式包是re,其中使用最多的几个函数为:

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

re.search 扫描整个字符串并返回第一个成功的匹配。

re.findall 在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。

本文将使用其中的函数,简单封装成一个便于输出的接口调用

import re#python常用的正则表达式包
def get_res(regex,text):
    res=re.findall(regex,text)
    print('findall res:',res)
    res=re.search(regex,text)
    print('search res:',res)

1.匹配单个字符

example 1: 单个字符

text="Hello, my name is Van. Please visit my website at https://www.zhihu.com/people/le-yifan-35."



    
get_res(r'Van',text)
findall res: ['Van']
search res: span=(18, 21), match='Van'>

example 2:匹配任何字符

text="sales1.xls\
orders3.xls\
sales2.xls\
sales3.xls\
apac1.xls\
europe2.xls"

get_res(r'sales.',text)
findall res: ['sales1', 'sales2', 'sales3']
search res: span=(0, 6), match='sales1'>

2. 匹配多个字符

example 1:匹配多个字符

text="sales1.xls\
orders3.xls\
sales2.xls\
sales3.xls\
apac1.xls\
europe2.xls\
na1.xls\
na2.xls\
sa1.xls\
ca1.xls"

get_res(r'[ns]a.\.xls',text)
findall res: ['na1.xls', 'na2.xls', 'sa1.xls']
search res: span=(61, 68), match='na1.xls'>

example 2:匹配多个字符

text="The phrase “regular expression” is often abbreviated as RegEx or regex."
get_res(r'[Rr]eg[Ee]x',text)
findall res: ['RegEx', 'regex']
search res: span=(56, 61), match='RegEx'>

example 3:设定字符的范围

text="sales1.xls\
orders3.xls\
sales2.xls\
sales3.xls\
apac1.xls\
europe2.xls\
na1.xls\
na2.xls\
sa1.xls\
ca1.xls"


get_res(r'[ns]a[0123456789]\.xls',text)

get_res(r'[ns]a[0-9]\.xls',text)
findall res: ['na1.xls', 'na2.xls',


    
 'sa1.xls']
search res: span=(61, 68), match='na1.xls'>
findall res: ['na1.xls', 'na2.xls', 'sa1.xls']
search res: span=(61, 68), match='na1.xls'>

example 4:设定字符的范围

text=""

get_res(r'[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]',text)

findall res: ['336633', 'FFFFFF']
search res: span=(16, 22), match='336633'>

example 5:取非匹配

text="sales1.xls\
orders3.xls\
sales2.xls\
sales3.xls\
apac1.xls\
europe2.xls\
sam.xls\
na1.xls\
na2.xls\
sa1.xls\
ca1.xls"


get_res(r'[ns]a[^0-9]\.xls',text)


findall res: ['sam.xls']
search res: span=(61, 68), match='sam.xls'>

3. 元字符

元字符指的是这个字符有特殊的含义,而不是字符本身的含义

example 1:元字符'[]'

text="var myArray = new Array();\
...\
if (myArray[0] == 0) {\
...\
}"

get_res(r'myArray[0]',text)

get_res(r'myArray\[0\]',text)
findall res: []
search res: None
findall res: ['myArray[0]']
search res: span=(33, 43), match='myArray[0]'>

example 2:元字符'\'

text="\ home\  ben\ sales\ "
get_res(r'\\',text)
findall res: ['\\', '\\', '\\', '\\']
search res: span=(0, 1), match='\\'>

example 3:空白字符

text="“101”,”Ben”,”Forta”\
“102”,”Jim”,”James”\r\n\
\r\n\
“103”,”Roberta”,”Robertson”\
“104”,”Bob”,”Bobson”"

get_res(r'\r\n\r\n',text)



    
findall res: ['\r\n\r\n']
search res: span=(38, 42), match='\r\n\r\n'>

example 4:数字元字符

text="var myArray = new Array();\
...\
if (myArray[0] == 0) {\
...\
}"

get_res(r'myArray\[\d\]',text)

findall res: ['myArray[0]']
search res: span=(33, 43), match='myArray[0]'>

example 5:字母数字元字符

text='11213 \
A1C2E3 \
48075 \
48237 \
M1B4F2 \
90046 \
H1H2H2'

get_res(r'\w\d\w\d\w\d',text)
findall res: ['A1C2E3', 'M1B4F2', 'H1H2H2']
search res: span=(6, 12), match='A1C2E3'>

4. 重复字符串匹配

example 1:匹配0个或者多个字符

text='Hello .ben@forta.com is my email address.'
get_res(r'\w+[\w.]*@[\w.]+\.\w+',text)
findall res: ['ben@forta.com']
search res: span=(7, 20), match='ben@forta.com'>
text="The URL is http://www.forta.com/, to connect securely use https://www.forta.com/ instead."
get_res(r"https?://[\w./]+",text)
findall res: ['http://www.forta.com/', 'https://www.forta.com/']
search res: span=(11, 32), match='http://www.forta.com/'>

example 2:

text=""

get_res(r"\d{6}",text)
findall res: ['336633']
search res: span=(16, 22), match='336633'>

example 3:范围匹配

text="4/8/03 \
10-6-2004 \
2/2/2 \
01-01-01"


get_res(r"\d{1,2}[-\/]\d{1,2}[-\/]\d{2,4}",text)
findall res: ['4/8/03', '10-6-2004', '01-01-01']
search res: span=(0, 6), match='4/8/03'>

example 4:至少多少 次数匹配

text="1001: $496.80 1002: $1290.69 1003: $26.43 1004: $613.42 1005: $7.61 1006: $414.90 1007: $25.00"

get_res(r"\d+: \$\d{3,}\.\d{2}",text)
findall res: ['1001: $496.80', '1002: $1290.69', '1004: $613.42', '1006: $414.90']
search res: span=(0, 13), match='1001: $496.80'>

example 5:防止过度匹配

text="This offer is not available to customers living in AK and HI."

get_res(r".*[Bb]>",text)

get_res(r".*?[Bb]>",text)
findall res: ['AK and HI']
search res: span=(51, 74), match='AK and HI'>
findall res: ['AK',
'HI']
search res: span=(51, 60), match='AK'>

5. 位置匹配

example 1:字符边界

text="The cat scattered his food all over the room."

get_res(r"cat",text)

get_res(r"\bcat\b",text)
findall res: ['cat', 'cat']
search res: span=(4, 7), match='cat'>
findall res: ['cat']
search res: span=(4, 7), match='cat'>

example 2:"\B"边界

text="Please enter the nine-digit id as it appears on your color - coded pass-key."

get_res(r'\B-\B',text)
print(text[55:63])

get_res(r'\b-\b',text)
findall res: ['-']
search res: span=(59, 60), match='-'>
lor - co
findall res: ['-', '-']
search res: span=(21, 22), match='-'>

example 3:字符串边界

text=" 

get_res(r'^\s*',text)

findall res: ['encoding=”UTF-8” ?>']
search res: span=(0, 39), match=' encoding=”UTF-8” ?>'>

6. 使用子表达式

example 1:子表达式

text="Hello, my name is Ben Forta, and I am the author of books on SQL, ColdFusion, WAP,\
Windows  2000, and other subjects."


get_res(r' {2,}',text)

get_res(r'( ){2,}',text)
findall res: []
search res: None
findall res: [' ']
search res: span=(94, 106), match='  '>

example 2:子表达式

text="Pinging hog.forta.com [12.159.46.200] with [12.159.89.200] 32 bytes of data:"
#findall中含有“()”时,只表示出子表达式特定位置的字符,见下文结果

get_res(r"(\d{1,3}\.){3}\d{1,3}",text)
findall res: ['46.', '89.']
search res: span=(23, 36), match='12.159.46.200'>

example 3:子表达式

text='ID: 042 \
SEX: M \
DOB: 1967-08-17 \
Status: Active'


get_res(r"19|20\d{2}",text)

get_res(r"(19|20)\d{2}",text)
findall res: ['19']
search res: span=(20, 22), match='19'>
findall res: ['19']
search res: span=(20, 24), match='1967'>

7.使用回溯

「回溯引用允许正则表达式模式引用前面的匹配结果。可以把回溯引用想象成一个变量。」

example 1:回溯

text='This is a block of of text, several words here are are repeated, and and they should not be.'

get_res(r"[ ]+(\w+)[ ]+\1",text)#\1 就是引用(\w+)的内容,表示第1个子表达式
findall res: ['of', 'are', 'and']
search res: span=(15, 21), match=' of of'>

example 2: 回溯

text=" \

Welcome to my Homepage

 \
Content is divided into two sections:
 

ColdFusion

 \
Information about Macromedia ColdFusion. 

Wireless

 \
Information about Bluetooth, 802.11, and more. 

This is not valid HTML \
"



get_res(r".*?[hH]\1>",text)
findall res: ['1', '2', '2']
search res: span=(7, 38), match='

Welcome to my

Homepage'>

8. 前后查找

前后查找(lookaround)对某一位置的前、后内容进行查找。

example 1:向前查找

text='http://www.forta.com/\n\
https://mail.forta.com/\n\
ftp://ftp.forta.com/\n'


get_res(r".+(?=:)",text)
findall res: ['http', 'https', 'ftp']
search res: span=(0, 4), match='http'>

example 2:向后查找

text='ABC01: $23.45\n\
HGG42: $5.31\n\
CFMX1: $899.00 XTC99: $69.96\n\
Total items found: 4'


get_res(r"(?<=\$)[0-9.]+",text)
findall res: ['23.45', '5.31', '899.00', '69.96']
search res: span=(8, 13), match='23.45'>

example 3:向前向后查找

text='\n\
Ben Forta’s Homepage\n\
'


get_res(r"(?<=).*(?=[tT][iI][tT][lL][eE]>)",text)
findall res: ['Ben Forta’s Homepage']
search res: span=(14, 34), match='Ben Forta’s Homepage'>

example 4:负向查找

text="I paid $30 for 100 apples, 50 oranges, and 60 pears. I saved $5 on this order."

get_res(r"(?,text)
findall res: ['0', '100', '50', '60']
search res: span=(9, 10), match='0'>

9. 嵌入条件

example 1:(?(backreference)true-regex)

text='\n\
\n\
\n\
\n\
\n\
\n\
 '

get_res(r"(]+>\s*)?]+>(?(1)\s*[Aa]>)",text)
findall res: ['', '', '', '', '']
search res: span=(22, 70), match='
'>

example 2:(?(backreference)true-regex|false-regex)

text='123-456-7890\n\
(123)456-7890\n\
(123)-456-7890\n\
(123-456-7890\n\
1234567890\n\
123 456 7890'


get_res(r"(\()?\d{3}(?(1)\)|-)\d{3}-\d{4}",text)
findall res: ['', '(', '']
search res: span=(0, 12), match='123-456-7890'>

代码

以上的东西我已经整理好了:

一文入坑正则表达式代码(https://github.com/weizaiff/regexp)

「所以外卖🥡该填哪个电话☎️呢?」


参  考  资  料

《正则表达式必知必会(修订版)》




由于微信平台算法改版,公号内容将不再以时间排序展示,如果大家想第一时间看到我们的推送,强烈建议星标我们和给我们多点点【在看】。星标具体步骤为:

(1)点击页面最上方"AINLP",进入公众号主页。

(2)点击右上角的小点点,在弹出页面点击“设为星标”,就可以啦。

感谢支持,比心

欢迎加入AINLP技术交流群
进群请添加AINLP小助手微信 AINLPer(id: ainlper),备注NLP技术交流

推荐阅读

这个NLP工具,玩得根本停不下来

完结撒花!李宏毅老师深度学习与人类语言处理课程视频及课件(附下载)

从数据到模型,你可能需要1篇详实的pytorch踩坑指南

如何让Bert在finetune小数据集时更“稳”一点

模型压缩实践系列之——bert-of-theseus,一个非常亲民的bert压缩方法

文本自动摘要任务的“不完全”心得总结番外篇——submodular函数优化

Node2Vec 论文+代码笔记

模型压缩实践收尾篇——模型蒸馏以及其他一些技巧实践小结

中文命名实体识别工具(NER)哪家强?

学自然语言处理,其实更应该学好英语

斯坦福大学NLP组Python深度学习自然语言处理工具Stanza试用

关于AINLP

AINLP 是一个有趣有AI的自然语言处理社区,专注于 AI、NLP、机器学习、深度学习、推荐算法等相关技术的分享,主题包括文本摘要、智能问答、聊天机器人、机器翻译、自动生成、知识图谱、预训练模型、推荐系统、计算广告、招聘信息、求职经验分享等,欢迎关注!加技术交流群请添加AINLPer(id:ainlper),备注工作/研究方向+加群目的。


阅读至此了,分享、点赞、在看三选一吧🙏

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/109898
 
339 次点击