其实写正则表达式的人,挺多的。但还是有朋友让黄同学再写一遍,那行吧,黄同学笔记早就有了,只不过感觉别人写的都很全了,不好意思班门弄斧。

既然我在写一次,我还是想写的精简一些,挑重点的讲。

1. 什么是“正则表达式”

“正则表达式” 是一组由字母和符号组成的特殊文本,可以帮助我们从某个复杂的字符串中,提取出满足我们要求的特殊文本。

用一个我理解的比喻带着大家体会 “正则匹配的过程”。苹果道具相当于写的“正则表达式”,水果市场相当于“字符串”,“正则匹配的过程”就相当于拿着苹果道具去“水果市场”找苹果的过程,每匹配到一个就返回一个,否则就什么也没有。

2. 常用“操作符”介绍

正则表达式之所以这么强大,是因为拥有很多专用的操作符(又称“元字符”)、特殊字符和修饰符。

所谓“元字符”,指的是那些不仅仅可以表示字符本身含义、并且还可以表示其他特殊含义的字符。常用的元字符有 . [ ] () ^ $ | \ ? * +{ }共11种,为了更加方便记忆和学习正则表达式,我将元字符再细化为7个普通元字符 + 4个常用量化符

特殊字符主要介绍了6个,\d、 \D、 \s、 \S、 \w、 \W

① 7个普通元字符

下面这7个符号,我相信并不太多,大家一定可以记忆下来,不行就设置为壁纸帮助记忆。黄同学真的是一分再分,只能简化这份上了。

② 4个常用量化符

所为“量化符”,指的就是将紧挨着量化符前面的那个字符,匹配0次、1次或者多次,详细说明见下表。

③ 6个特殊符号

所为“特殊符”,指的就是由转义字符加某些字母组合而成的,具有特殊意义的特殊字符,详细说明见下表。

④ 3个常用修饰符

其实正则表达式中的修饰符不止3个,但是我只挑重要的给大家讲,详细说明见下表。

3. 常用方法介绍

其中三个函数用于查找匹配match()、search()、findall(),一个函数sub()用于替换,还有一个函数compile()用于编译正则表达式。

在分别讲述这些函数之前,我们分别讲述一下这些函数的含义。

  • match():匹配字符串的开头,如果开头匹配不上,则返回None;
  • search():扫描整个字符串,匹配后立即返回,不在往后面匹配;
  • findall():扫描整个字符串,以列表形式返回所有的匹配值;
  • compile():将字符串编译成正则表达式对象,供 match() 、 search() 和findall()函数使用;
  • sub():扫描整个字符串,用于替换字符串的某些值;
  • split():扫描整个字符串,按照指定分隔符切分字符串;
① match(pattern,string,flag)

match()函数语法格式如下:

  • pattern:你写的正则表达式;
  • string:待匹配的字符串;
  • flag:修饰符;

首先咱们来演示match()函数的用法。对于这样一个字符串s1:

s1 = 'ab黄cd同abc学'

需求一:我们想要得到字符串s1中的a,使用match()函数应该怎么做。

re.match('a',s1)

结果如下:

可以发现:这里得到的是一个match对象,并没有任何的结果。那么,怎么获取到具体的值。

直接调用对象的group()函数,可以获取到具体的值。

s1 = 'ab黄cd同abc学'
r1 = re.match('a',s1)
r1.group()

结果如下:

可以发现,match()函数一旦匹配到具体值,就立即返回,不再往后面匹配。因此,这里只返回了一个’a’。

需求二:我们现在不想匹配字符串s1中的a,而是想匹配s1中的b,又应该怎么做呢?

s1 = 'ab黄cd同abc学'
r2 = re.match('b',s1)
r2.group()

结果如下:

此时可以发现:报错了。这是由于match()函数只能从字符串开头匹配,如果开头没有匹配上,则会报错。因为字符串s1是以a开头,不是以b开头,所以匹配不上。

注:这个函数局限性太大,用的不是太多,因此大家知道这个事儿就行。match()函数主要是用于区分下面要讲的search()函数。

② search(pattern, string,flag)

search()函数语法格式如下:

  • pattern:你写的正则表达式;
  • string:待匹配的字符串;
  • flag:修饰符;

还是同样的一个字符串s1:

s1 = 'ab黄cd同abc学'

需求一:我们想要得到字符串s1中的a,使用search()函数应该怎么做。

s1 = 'ab黄cd同abc学'
r2 = re.search('a',s1)
r2.group()

结果如下:

需求二:使用search()函数,去匹配字符串s1中的b。

s1 = 'ab黄cd同abc学'
r2 = re.search('b',s1)
r2.group()

结果如下:

search()函数与match()函数不同点:match()函数如果开头匹配不上,就无法匹配。search()函数是扫描整个字符串,只要能匹配上,就有结果。

search()函数与match()函数相同点:它们一旦匹配上了,就立即返回结果,而不再往后面匹配(即使后面能匹配上)。如果都匹配不上,会出现同样的错误,如下图所示:

注意:search()函数比match()函数要实用一些,有时候我们只想匹配字符串的,第一个匹配值,后面的匹配值我们不想要,search()函数可以很好的帮忙。

③ findall(pattern, repl, string, count=0, flags=0)

findall()函数语法格式如下:

  • pattern:你写的正则表达式;
  • string:待匹配的字符串;
  • flag:修饰符;

findall()函数,不管是我们做爬虫,还是我们做数据清洗,都属于高频函数,大家一定要好好掌握。

我们先看一个简单的例子:

还是前面的字符串s1,我们分别只想获取a、只想获取b、获取a或b,使用findall()会出现什么结果呢?

s1 = 'ab黄cd同abc学'
re.findall('a',s1)re.findall('b',s1)re.findall('[a | b]',s1)

结果如下:

可以发现:finadll()函数会直接返回所有匹配对象,组成的列表(记住:返回的是列表),不像search()函数与match()函数,还需要调用group()函数,这个大家一定要注意。

如果finadll()函数,没有匹配上,不会报错,而是返回一个空列表。

s1 = 'ab黄cd同abc学'
re.findall('f',s1)

结果如下:

我们在来看一个稍微复杂一点的案例(爬虫经常见到的)

html = '''<html>
<head lang="en">
<title>Title</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body><div id="content"><ul id="ul1"><li>first</li><li>second</li><li>third</li></ul><ul id="ul2"><li>alpha</li><li>beta</li></ul></div><div id="url"><a href="http:www.baidu.com" title="baidu">baidu</a><a href="http:www.tipdm.com" title="tipdm">tipdm</a></div>
</body>
</html>
'''

如果我们想要使用正则表达式,获取其中的li标签,或者获取其中的href属性,应该怎么做呢?

# 获取li标签
re.findall('<li>(.*?)</li>',html)# 获取href属性
re.findall('<a href="(.*?)" ',html)

结果如下:

操作其实很简单,固定写法:首尾照抄字符串源代码,我们想要的东西使用()小括号,括起来,里面写上 .*?

上面提到了一个.*与.*?,其中.*表示贪婪匹配,.*?表示非贪婪匹配。

  • . 可以匹配除了换行符以外的所有字符;
  • *表示匹配前面的字符无限次;
  • ?前面紧挨的元素,最多匹配一次;

我们用一个例子简单说明:

s2 = 'a123b456b789b3'
re.findall('a(.*)3',s2)
re.findall('a(.*?)3',s2)

结果如下:

用一句通俗的话说明它们的区别:贪婪匹配是尽可能多的匹配内容,非贪婪匹配是尽可能少的 匹配内容。字符串s2中有两个3,贪婪匹配会一直匹配到最后一个3,但是非贪婪匹配找到第一个3后,就停止了。

④ compile()

compile函数将字符串编译成正则表达式对象,供 match() 、 search() 和findall()函数使用。

即:先定义一个正则表达式对象(Pattern对象),然后分别调用该对象的match() 、 search() 和findall()函数,这三个函数用法与它们原本用法相同。

我们直接用一个例子讲述该函数:

type(re.compile(r'\d+'))

结果如下:

可以看到这是一个Pattern对象。

s3 = '12one34two56three78four'
# 定义一个正则表达式对象,用于匹配至少一个数字
pattern = re.compile(r'\d+')
# 扫描整个字符串,匹配s3字符串中,符合该正则表达式的字符串。(这里调用的是对象的findll()对象)。
pattern.findall(s3)
# 从s3字符串,下标为1的位置,查找匹配值。
pattern.findall(s3,1)
# 从s3字符串,下标为1到下标为6的位置之间,查找匹配值。
pattern.findall(s3,1,6)

结果如下:

⑤ sub(pattern, repl, string, count, flags)

sub()函数是Python正则表达式中,专门用于“替换”的函数。

sub()函数语法格式如下:

  • pattern:你写的正则表达式;
  • repl:替换成啥;
  • string:待替换的字符串;
  • count:表示最大替换次数,默认 0 表示替换所有的匹配;
  • flag:修饰符;

同样对于上述提到的字符串s3,我们将“英文字母” 全部替换为 “字母”两个字,应该做么办呢?

# '\D{3,5}'表示匹配非数字3-5次。
s3 = '12one34two56three78four'
# 这里没有指定最大匹配次数,因此默认会替换所有的匹配值
re.sub('\D{3,5}','字母',s3)
# 这里指定最大匹配次数count=2,因此只会替换前2个匹配值
re.sub('\D{3,5}','字母',s3,2)
# 如果count=3,则会替换3个匹配值
re.sub('\D{3,5}','字母',s3,3)

结果如下:

⑥ split(pattern, string, maxsplit, flags)

split()函数是Python正则表达式中,专门用于“切分字符串”的函数。

split()函数语法格式如下:

  • pattern:你写的正则表达式;
  • string:待分割的字符串;
  • maxsplit:最大分割次数,默认为 0,表示不限制分割次数;
  • flag:修饰符;

有这样一个字符串s4,我们以“-”为分隔符切分字符串,看看使用split()函数会得到什么样的结果。

# '\D'表示匹配非数字
s4 = '136-3456-7413'
# 这里如果不指定“最大分割次数”,则是不限次数切分
re.split('\D',s4)
# 如果指定最大分割次数maxsplit=1,那么就只以第一个分隔符,进行切分
re.split('\D',s4,1)

结果如下:

限于篇幅!这篇文章就讲述到这里。当然,关于正则表达式中剩下的一些用法(比如说普通元字符、量化符、修饰符的用法),还有第二篇文章。

一级棒!这应该是最好的 “re正则表达式” 使用教程了!相关推荐

  1. 盐城北大青鸟:Java的四大就业方向,薪资也是一级棒

    近几年,由于互联网的快速发展,有许多新兴的语言和技术逐渐进入我们的视野,导致唱衰Java即将"走下神坛"的声音不绝于耳,真的是这样吗? 数据是从来不会骗人的,根据官方发布的最新TI ...

  2. A*算法详解(讲的一级棒 )

    转自:https://blog.csdn.net/hitwhylz/article/details/23089415 概述 虽然掌握了 A* 算法的人认为它容易,但是对于初学者来说, A* 算法还是很 ...

  3. sega游戏_SEGA 宇宙骑警 画面音效操作感一级棒的 驾驶类街机游戏

    各位朋友们大家好,欢迎来到e天空游乐城,今天的经典游戏推荐节目给大家带来的是 SEGA公司在街机平台上推出的一款驾驶类游戏<宇宙骑警>这款游戏相信70,80年代的朋友应该不会陌生. 游戏的 ...

  4. 戴尔电脑怎么安装一级计算机,手把手教你戴尔笔记本电脑重装系统教程

    随着生活质量的提高,现今基本上人人都拥有一台专属于自己的笔记本电脑.但要是说起笔记本,那dell笔记本可是一个不错的品牌呢?所以小编今天要给大家说的知识点就是关于Dell笔记本怎么重装系统的内容.有兴 ...

  5. 计算机一级改扩展名,如果改变文件扩展名 修改教程分享【图解】

    导读:我们在使用电脑的过程当中,经常需要新建文件夹,文件夹的种类有很多,它的后缀不同,那么这个文件夹的类型就不同,当我们已经新建号一个文件夹以后,不想使用此类型的文件,当我们对文件夹的后缀进行修改的过 ...

  6. “勤奋”,是能让你走出低谷最有效的方法

    说起"勤奋",我又想起我刚开始出来工作的时候:因为我想让生活过得更好,所以我必须要做两份工作,这样收入就可以更高一点,会离我的目标更近一点. 同时,每当我有休息日都会把我们的服装宿 ...

  7. 1024 程序员节 | 请对身边的程序猿好一点

    程序员节起源 程序员的工作我们都知道,编程嘛.但为什么程序员节要在1024呢?1024最早火起来是因为一个"不可描述"的论坛,那里的回帖机制是:新用户发过贴之后,过1024秒才能发 ...

  8. 分享一些自己常用的科研/软件工具

    来自:知乎,作者:花花 链接:https://zhuanlan.zhihu.com/p/68364849 前段时间实习挺忙的,没什么时间写文章,原本有个MCTS的坑估计已经无限延期了.端午节放假可以休 ...

  9. 强烈推荐8个值得下载的神仙软件,每一个都让人惊喜

    给大家分享8个非常实用,功能强大的软件,每一款都让人惊艳,可以解决很多问题. 1.Snipaste Snipaste是出色的截图贴图软件.Snipaste截图非常强悍.第一个特点就是截图精确智能.可以 ...

  10. 闲话机器人领域的国际会议

    原文来自小木虫:闲话机器人领域的国际会议 原文书接上一回,见帖http://muchong.com/bbs/viewthread.php?tid=4495593.上回大话了机器人领域的SCI期刊杂志, ...

最新文章

  1. ES6 let和const 命令
  2. js图片压缩并上传?
  3. 边缘计算 — 与硬件厂商
  4. 我的图床设置PicGo
  5. 在eclipse中new 对象后怎么通过快捷键自动生成返回对象
  6. 【VMware vSAN 6.6】6.2.启用性能服务:vSAN硬件服务器解决方案
  7. (第十二章)创建数据表索引
  8. vue.js能美化界面吗_美牙真的能变美吗?刘涛花百万美化牙齿,容貌大变样,网友:太神奇了吧...
  9. SQL Server 2008 报表服务入门
  10. 【转载】TreeView序列化,TreeView串行化,TreeView反序列化 c# winform
  11. win10重装,检测到硬盘错误:在MBR硬盘上没有找到可以引导的分区
  12. java实习面试题整理
  13. 由于找不到iutils.dll无法继续执行代码?
  14. 低级程序员和高级程序员的区别,难道这就是最强王者的世界吗?
  15. 2018前端走向全栈,Nodejs快速入门视频教程
  16. matlab生成s加减速曲线,一种基于移动平均算法的S曲线加减速控制方法与流程
  17. 输入远程计算机地址后,不提示输入用户名密码直接进入计算机怎么回事,解决Windows远程桌面连接每次都提示输入密码的问题...
  18. Apache POI读合并单元格
  19. 基于Java+控制台实现车辆信息管理系统
  20. 刘汝佳《算法竞赛入门经典》---总结

热门文章

  1. 【模式串匹配】Aho-Corasick algorithm - AC字符串匹配算法实现与测试【Python】
  2. CentOS7安装Chrome浏览器
  3. 基于SpringBoot体育用品购物商城-协同过滤推荐算法项目源代码
  4. 拉格朗日法线性规划求解
  5. 电子科大考研经验分享
  6. 基于区块链的数字藏品管控方案
  7. 十个Win10使用小技巧,看看你知道哪些?
  8. pwnablekr-asm-seccomp-sandbox
  9. Python 基础知识 Day2
  10. Web前端零基础入门HTML5+CSS3基础教程——了解前端