正则表达式是一种用来匹配字符串的强有力的武器。它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的。

1 正则表达式

1.1 定位符

行定位符就是用来描述字符串的边界,“^”表示行的开始,“$”表示行的结尾。

^tm     # 表示要匹配字符串tm的开始位置是行头
tm$     # 表示要匹配字符串tm的结束位置是行尾

1.2 元字符

除了上一节介绍的元字符“^”“$”外,正则表达式还有更多的元字符,见下图。

图1 常用元字符

假设你在一篇英文小说里查找hi,你可以使用正则表达式hi。不幸的是,很多单词里包含hi这两个连续的字符,比如him,history,high等等。用hi来查找的话,这里边的hi也会被找出来。如果要精确地查找hi这个单词的话,我们应该使用\bhi\b

\b是正则表达式规定的一个特殊代码(某些地方叫它元字符,metacharacter),代表着单词的开头或结尾,也就是单词的分界处。虽然通常英文的单词是由空格,标点符号或者换行来分隔的,但是\b并不匹配这些单词分隔字符中的任何一个,它只匹配一个位置。

1.3 限定符

我们知道,使用(\w*)匹配任意数量的字母或数字,如果想匹配特定数量的数字,就需要使用限定符(指定数量的字符)来实现该功能,如果匹配8位QQ号可用如下表达式:

^\d{8}$

图2 常用限定符

1.4 字符类

正则表达式查找数字和字母是很简单的,因为已经有了对应这些字符集合的元字符(如\d\w),但是如果要匹配没有预定义元字符的字符集合(比如元音字母a, e, i, o, u),应该怎么办?

很简单,只需要在方括号里列出它们就行了,像[aeiou]可以匹配任何一个英文元音字母,[.?!]匹配标点符号(“.” “?”或“!”)。也可以轻松地指定一个字符范围,像[0-9]代表的含义与\d就是完全一致的:一位数字;同理,[a-z0-9A-Z_]完全等同于\w(如果只考虑英文的话)。

说明:要想匹配给定字符串中任意一个汉字,可以使用[\u4e00-\u9fa5];如果要匹配连续多个汉字,可以使用[\u4e00-\u9fa5]+

1.5 排除字符

在1.1小节列出的是匹配符合指定字符集合的字符串。现在反过来,匹配不符合指定字符集合的字符串。正则表达式提供了^字符。这个元字符在1.1小节中出现过,表示行的开始。而这里将会放到方括号中,表示排除的意思。例如:

[^a-zA-Z]

该表达式用于匹配一个不是字母的字符串。

1.6 选择字符

试想一下,如何匹配身份证号码?首先需要了解一下身份证号码的规则。身份证号码长度为15位或者18位。如果为15位时,则全为数字;如果为18位时,前17位为数字,最后一位是校验位,可能为数字或字符X。
在上面的描述中,包含着条件选择的逻辑,这就需要使用选择字符(|)来实现。该字符可以理解为‘或’,匹配身份证的表达式可以写成如下方式:

(^\d{15}$)|(^\d{18}$)|(^\d{17})(\d|X|x)$)

该表达式的意思是以匹配15位数字,或者18位数字,或者17位数字和最后一位。最后一位可以是数字,也可以是X或者x

1.7 转义字符

正则表达式中的转义字符()和Python中的大同小异,都是将特殊字符(如“”“?”“|”等)变为普通的字符。举一个IP地址的实例,用正则表达式匹配诸如“127.0.0.1”格式的IP地址。如果直接使用点字符,格式为:

[1-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}

这显然不对,因为“.”可以匹配一个任意字符。这时,不仅是127.0.0.1这样的IP,连127101011这样的字符串也会被匹配出来。所以在使用“.”时,需要使用转义字符)。修改后上面的正则表达式格式为:

[1-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}

1.8 分组

通过1.6小节中的例子,相信读者已经对小括号的作用有了一定的了解。小括号字符的第一个作用就是可以改变限定符的作用范围,如“|”、“*”、“^”等。例如下面的表达式中包含小括号。

(six|four)th

这个表达式的意思是匹配单词sixthfourth,如果不使用小括号,那么就变成了匹配单词sixfourth了。
小括号的第二个作用是分组,也就是子表达式。如(\.[0-9]{1,3}){3},就是对分组(\.[0-9]{1,3})进行重复操作。

由于模式字符串中可能包括大量的特殊字符和反斜杠,所以需要写为原生字符串,即在模式字符串前加r或R。例如,模式字符串采用原生字符串表示为:

r`\bm\w*\b`

推荐几个正则表达式在线测试工具,

  • 菜鸟工具:https://c.runoob.com/front-end/854/
  • Regulex:https://jex.im/regulex/#!flags=&re=%5B0-9%5D%2B
  • RegExr:https://regexr.com/

2 Re模块

Python提供了re模块,用于实现正则表达式的操作。在实现时,可以使用re模块提供的方法(如search()match()findall()等)进行字符串处理,也可以先使用re模块的compile()方法将模式字符串转换为正则表达式对象,然后再使用该正则表达式对象的相关方法来操作字符串。下面是re模块中的核心函数。

2.1 编译表达式

compile函数用于编译正则表达式,生成一个正则表达式(Pattern)对象,供 match()search()这两个函数使用。]
参数说明:

  • pattern:表示模式字符串,由要匹配的正则表达式转换而来。
  • flags:可选参数,表示标志位,用于控制匹配方式,如是否区分字母大小写。常用的标志如图3所示。

图3 常用标志

语法格式为:

re.compile(pattern[, flags])

2.2 匹配字符串

匹配字符串可以使用re模块提供的match()search()findall()等方法。

1. 使用match()方法进行匹配

match()方法用于从字符串的开始处进行匹配,如果在起始位置匹配成功,则返回Match对象,否则返回None。其语法格式如下:

re.match(pattern, string, [flags])

参数说明:

  • pattern:表示模式字符串,由要匹配的正则表达式转换而来。
  • string:表示要匹配的字符串。
  • flags:可选参数,表示标志位,用于控制匹配方式,如是否区分字母大小写。常用的标志如图3所示。

例如,匹配字符串是否以mr_开头,不区分字母大小写,代码如下:

import re
pattern = re.compile(r'mr_\w+', re.I)   # 模式字符串,不区分大小写
string1 = 'MR_SHOP mr_shop'  # 要匹配的字符串
m1 = pattern.match(string1)
print(m1)   # <re.Match object; span=(0, 7), match='MR_SHOP'>
string2 = '项目名称 MR_SHOP mr_shop'
m2 = pattern.match(string2)
print(m2)   # None

由上面的结果我们可以看到,match()方法从字符串的开始位置开始匹配,如果匹配成功,则返回一个Match对象包含了匹配值的位置和匹配数据。其中,要获取匹配值的起始位置可以使用Match对象的start()方法;要获取匹配值的结束位置可以使用end()方法;通过span()方法可以返回匹配位置的元组;通过string属性可以获取要匹配的字符串。例如下面的代码:

import repattern = re.compile(r'mr_\w+', re.I)  # 模式字符串,不区分大小写
string1 = 'MR_SHOP mr_shop'  # 要匹配的字符串
m1 = pattern.match(string1)print('匹配值的起始位置:', m1.start())
print('匹配值的结束位置:', m1.end())
print('匹配位置的元组:', m1.span())
print('要匹配的字符串:', m1.string)
print('匹配数据:', m1.group())

执行结果如下:

匹配值的起始位置: 0
匹配值的结束位置: 7
匹配位置的元组: (0, 7)
要匹配的字符串: MR_SHOP mr_shop
匹配数据: MR_SHOP

2. 使用search()方法进行匹配
        search()方法用于在整个字符串中搜索第一个匹配的值,如果匹配成功,则返回Match对象,否则返回None。search()方法的语法格式如下:

re.search(pattern, string, [flags])

参数说明:

  • pattern:表示模式字符串,由要匹配的正则表达式转换而来。
  • string:表示要匹配的字符串。
  • flags:可选参数,表示标志位,用于控制匹配方式,如是否区分字母大小写。

搜索第一个以mr_开头的字符串,不区分字母大小写,代码如下:

import repattern = re.compile(r'mr_\w+', re.I)  # 模式字符串,不区分大小写
string1 = 'MR_SHOP mr_shop'  # 要匹配的字符串
match = pattern.search(string1)
print(match)
string2 = '项目名称 MR_SHOP mr_shop'
match = pattern.search(string2)
print(match)

执行结果如下:

<re.Match object; span=(0, 7), match=‘MR_SHOP’>
<re.Match object; span=(5, 12), match=‘MR_SHOP’>

  1. 使用findall()方法进行匹配

findall()方法用于在整个字符串中搜索所有符合正则表达式的字符串,并以列表的形式返回。如果匹配成功,则返回包含匹配结构的列表,否则返回空列表。findall()方法的语法格式如下:

re.findall(pattern, string, [flags])
  • pattern:表示模式字符串,由要匹配的正则表达式转换而来。
  • string:表示要匹配的字符串。
  • flags:可选参数,表示标志位,用于控制匹配方式,如是否区分字母大小写。

搜索以mr_开头的字符串,不区分字母大小写,代码如下:

import repattern = re.compile(r'mr_\w+', re.I)  # 模式字符串,不区分大小写
string1 = 'MR_SHOP mr_shop'  # 要匹配的字符串
m1 = pattern.match(string1)
string2 = '项目名称 MR_SHOP mr_shop'
m2 = pattern.match(string2)
match = pattern.findall(string1)
print(match)
match = pattern.findall(string2)
print(match)

执行结果如下:

[‘MR_SHOP’, ‘mr_shop’]
[‘MR_SHOP’, ‘mr_shop’]

2.3 替换字符串

sub()方法用于实现字符串替换,语法格式如下:

re.sub(pattern, repl, string, count, flags)

参数说明:

  • pattern:表示模式字符串,由要匹配的正则表达式转换而来。
  • repl:表示替换的字符串。
  • string:表示要被查找替换的原始字符串。
  • count:可选参数,表示模式匹配后替换的最大次数,默认值为0,表示替换所有的匹配。
  • flags:可选参数,表示标志位,用于控制匹配方式,如是否区分字母大小写。

替换敏感字符,代码如下:

import re
pattern = re.compile(r'(黑客)|(抓包)|(监听)|(Trojan)')
string = "我是一名程序员,我喜欢看黑客方面的书,想研究一下Trojan。\n"
sub = pattern.sub('@_@', string)
print(sub)  # 输出为:我是一名程序员,我喜欢看@_@方面的书,想研究一下@_@。

2.4 分割字符串

split()方法用于实现根据正则表达式分割字符串,并以列表的形式返回。其作用同字符串对象的split()方法类似,所不同的就是分割字符由模式字符串指定。split()方法的语法格式如下:

re.split(pattern, string, [maxsplit], [flags])

参数说明:

  • pattern:表示模式字符串,由要匹配的正则表达式转换而来。
  • string:表示要匹配的字符串。
  • maxsplit:可选参数,表示最大的拆分次数。
  • flags:可选参数,表示标志位,用于控制匹配方式,如是否区分字母大小写。

例如,从给定的URL地址中提取出请求地址和各个参数,代码如下:

pattern = re.compile(r'[?|&]')
url = 'http://www.mingrisoft.com/login.jsp?username="mr"&pwd="mrsoft"'
result = pattern.split(url)
print(result)   # 输出为:['http://www.mingrisoft.com/login.jsp', 'username="mr"', 'pwd="mrsoft"']

小结:

函数 说明
re.compile(pattern, flags=0) 编译正则表达式返回正则表达式对象
re.match(pattern, string, flags=0) 用正则表达式匹配字符串 成功返回匹配对象 否则返回None
re.search(pattern, string, flags=0) 搜索字符串中第一次出现正则表达式的模式 成功返回匹配对象 否则返回None
re.split(pattern, string, maxsplit=0, flags=0) 用正则表达式指定的模式分隔符拆分字符串 返回列表
re.sub(pattern, repl, string, count=0, flags=0) 用指定的字符串替换原字符串中与正则表达式匹配的模式 可以用count指定替换的次数
re.fullmatch(pattern, string, flags=0) match函数的完全匹配(从字符串开头到结尾)版本
re.findall(pattern, string, flags=0) 查找字符串所有与正则表达式匹配的模式 返回字符串的列表
re.finditer(pattern, string, flags=0) 查找字符串所有与正则表达式匹配的模式 返回一个迭代器
re.purge() 清除隐式编译的正则表达式的缓存
re.I / re.IGNORECASE 忽略大小写匹配标记
re.M / re.MULTILINE 多行匹配标记

参考

  • 正则表达式30分钟入门教程:https://deerchao.cn/tutorials/regex/regex.htm
  • 字符串和正则表达式:https://github.com/jackfrued/Python-100-Days/blob/master/Day01-15
  • Python3 正则表达式:https://www.runoob.com/python3/python3-reg-expressions.html

Python基础篇(九)-- 正则表达式相关推荐

  1. 杨洋python课程提高篇_杨洋老师《全民一起玩Python 基础篇+提高篇》

    全民一起玩Python 基础篇+提高篇 适用人群: 想用轻松系统的方式,从零开始真正理解掌握Python.进而学习办公.网抓.数据.AI.网站等技术的各界人士 课程概述: 制作精细.自带吐槽,每节课程 ...

  2. 杨洋python课程提高篇_杨洋老师:全民一起玩Python 基础篇+提高篇,老师幽默严谨不枯燥的学习编程...

    课程介绍 本套课程出自杨洋老师的全民一起玩Python 基础篇+提高篇官网售价299元,程保持了杨洋博士老师幽默严谨不枯燥的学习编程,清晰全面的授课风格,配有丰富的教学演示和插图.动画,是初学者学习P ...

  3. 面试题之第一部分(Python基础篇) 80题

    第一部分(python基础篇)80题 为什么学习Python?==*== # 1. python应用于很多领域,比如后端,前端,爬虫,机器学习(人工智能)等方面,几乎能涵盖各个开发语言的领域,同时它相 ...

  4. python包括哪些部分_第一部分 Python基础篇

    第⼀一部分 Python基础篇 1. 为什什么学习Python? 朋友推荐,比较简单易学,生态圈比较强大 发展趋势:人工智能.数据分析 2. 通过什什么途径学习的Python? 廖雪峰.网络博客.相关 ...

  5. Python基础(九)--异常

    Python基础(九)--异常 1 异常相关概念 1.1 什么是异常 异常是程序运行过程中产生的一种事件,该事件会打乱程序的正常流程.可以说,异常就是一种意外,指程序没有按照正常或期望的方式执行. 当 ...

  6. 经典Python面试题之Python基础篇

    Python基础篇 1. 为什么学习Python? 2. 通过什么途径学习的Python? 3. Python和Java.PHP.C.C#.C++等其他语言的对比? 4. 简述解释型和编译型编程语言? ...

  7. python 基础 之 re正则表达式的知识点整理,并简单使用说明

    python 基础 之 re正则表达式的知识点整理,并简单使用说明 目录 python 基础 之 正则表达式的知识点整理,并简单使用说明 一.简单介绍

  8. Python基础篇:你好,世界!

    Python基础篇:你好,世界! 开了一段时间的博客了,可能很多人都对Python基础不掌握或者掌握不牢固,所以我会分别出算法篇和基础篇的教程来教大家一步一步走向程序员的水平 接着我们看看下面这行代码 ...

  9. Python基础篇(七)

    Python基础篇(七) 前言 一.元组 1.1 元组的定义 1.2 元组的常见操作 二.字典 2.1 字典的语法 2.2 字典常见操作 2.3 字典的循环遍历 三.任务清单 3.1 基础练习 3.2 ...

  10. pythondd_工程脚本插件方案 - c集成Python基础篇

    工程脚本插件方案 - c集成Python基础篇 序: 为何要集成脚本,怎样在工程中集成Python脚本. 在做比较大型的工程时,1般都会分核心层和业务层.核心层要求实现高效和稳定的基础功能,并提供调用 ...

最新文章

  1. 2018会考计算机成绩查询入口,2018年山东会考成绩查询时间及入口
  2. 从本机发送信息到另一台服务器上时中文乱码
  3. java linkedlist排序_用Java对用户定义对象的LinkedList进行排序
  4. Linux国内源介绍
  5. SUSE Linux SFTP服务器配置
  6. java web临时文件删除_什么时候删除Java临时文件?
  7. c 和php 加密,加载由blenc加密的页面时出错(C和PHP代码)
  8. linux如何导入种子文件格式,在 Linux 上使用 transmission 制作种子
  9. 错误HIERARCHY_REQUEST_ERR: DOM Exception 3
  10. Open XML之我见
  11. InDesign转曲字体 导出PDF的技巧
  12. 合同管理系统操作手册
  13. LOAP引擎:clickhouse03:文件的导入导出方式
  14. UPnP 协议栈的威胁分析及防范方案
  15. qart 图形二维码 html2canvas下载二维码
  16. 蓝桥杯 T32大臣的旅费
  17. uestc 1593 老司机破阵(线段树 or multiset)
  18. 7-41 哥尼斯堡的“七桥问题” (25 分)
  19. 转载:html打开本地文件夹读取,显示图片
  20. 某易—将军令动态刨析算法(1)

热门文章

  1. the remote end hung up unexpectedly Everything up-to-date
  2. Ubuntu16.4打开优盘的错误,unnable to access
  3. 一款游戏让你成为 Vim 高手!
  4. 寓教于乐!一款游戏让你成为 Vim 高手!
  5. windows10 访问网页的时候提示找不到服务器IP地址如何处理
  6. 搭建嵌入式开源开发环境
  7. 75道逻辑思维题及答案
  8. 为什么美团股价大跌:疫情影响、阿里竞争与模式弊病
  9. C#指定图片添加文字——修改版
  10. 国行版苹果 ios 按键精灵无法联网问题处理