一、正则语句介绍

语法 说明 表达式示例 完整匹配的字符串
一般字符 匹配自身 abc abc
. 除换行符'\n'以外的任意字符 a.c abc
\ 转义字符,是后一个字符改变原来的意思 a\.c a.c
[...] 字符集,所有的特殊字符在字符集中都失去其原有的特殊含义 a[bcd]e abe  ace  ade
\d 数字[0-9] a\dc a1c
\D 非数字[^\d] a\Dc abc
\s 空白符 [<空格>\t\r\n\f\v] a\sc a c
\S  非空白字符[^\s] a\Sc abc
\w 单词字符[A-Za-z0-9_] a\wc abc
\W 非单词字符 [^\W] a\Wc a c
* 匹配前一个字符0或无限次 abc* ab   abcccccc
+ 匹配前一个字符1次或无限次 abc+

abc abccccc

? 匹配前一个字符0或1次 abc? ab abc
{m} 匹配前一个字符m次 ab{2}c abbc
{m,n} 匹配前一个字符m到n次 ab{1,2}c abc  abbc
^ 开头 ^abc abc
$ 末尾 abc$ abc
\A 仅匹配字符串开头
\Z 仅匹配字符串末尾
\b 匹配单词和非单词之间 a\b!bc a!bc
\B [^\b] a\Bbc abc
| 左右表达式任意匹配一个(先尝试左边) abc|def

abc

def

(...) 分组表达式

(abc){2}

abcabc
(?P=name) 分组,除了原有的编号外在指定一个额外的别名
\<number> 引用编号为<number>的分组匹配到的字符串
(?P=name) 引用别名为<name>的分组匹配到的字符串

1、贪婪模式

正则表达式通常用于在文本中查找匹配的字符串。Python里数量词默认是贪婪的,总是尝试匹配尽可能多的字符;非贪婪的则相反,总是尝试匹配尽可能少的字符。例如:正则表达式"ab"如果用于查找"abbbc",将找到"abbb"。而如果使用非贪婪的数量词"ab?",将找到"a"。

2. 反斜杠的困扰

正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"\",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\\\\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。

3. 匹配模式

正则表达式提供了一些可用的匹配模式,比如忽略大小写、多行匹配等

二、re模块简介

聊到Python正则表达式的支持,首先肯定会想到re库,这是一个Python处理文本的标准库

标准库的意思表示这是一个Python内置模块,不需要额外下载,目前Python内置模块大概有300个。可以在这里查看Python所有的内置模块:Python Module Index — Python 3.10.3 documentation

因为re是内置模块,所以不需要再下载,使用时直接引入即可:   import re

re模块官方文档:re --- 正则表达式操作 — Python 3.8.13 文档

re模块库源码:https://github.com/python/cpython/blob/3.8/Lib/re.p

三、re模块常量

常量即表示不可更改的变量,一般用于做标记。

re模块中有9个常量,常量的值都是int类型

1. IGNORECASE

语法: re.IGNORECASE 或简写为 re.I

作用: 进行忽略大小写匹配。

代码案例:

text = '这是一个例子b'
pattern = r'这是一个例子B'
print('默认模式', re.findall(pattern, text))
print('忽略大小写', re.findall(pattern, text, re.I))默认模式:[]
忽略大小写:['这是一个例子B']

在默认匹配模式下大写字母B无法匹配小写字母b,而在 忽略大小写 模式下是可以的。

2. ASCII

语法: re.ASCII 或简写为 re.A

作用: 顾名思义,ASCII表示ASCII码的意思,让 \w, \W, \b, \B, \d, \D, \s\S 只匹配ASCII,而不是Unicode。

代码案例:

text = '这是a一个例子b'
pattern = r'\w+'
print('Unicode', re.findall(pattern, text))
print('ASCII', re.findall(pattern, text, re.A))Unicode:['这是a一个例子b']
ASCII:['a','b']

在默认匹配模式下\w+匹配到了所有字符串,而在ASCII模式下,只匹配到了a、b、c(ASCII编码支持的字符)。

注意:这只对字符串匹配模式有效,对字节匹配模式无效。

3. DOTALL

语法: re.DOTALL 或简写为 re.S

作用: DOT表示.,ALL表示所有,连起来就是.匹配所有,包括换行符\n默认模式下.是不能匹配行符\n

代码案例:

text = '这是一个\n例子'
pattern = r'.*'
print('默认模式', re.findall(pattern, text))
print('匹配所有模式', re.findall(pattern, text, re.S))默认模式:['这是一个', '', '例子', '']
匹配所有模式:['这是一个\n例子', '']

在默认匹配模式下.并没有匹配换行符\n,而是将字符串分开匹配;而在re.DOTALL模式下,换行符\n与字符串一起被匹配到。

注意:默认匹配模式下.并不会匹配换行符\n

4. MULTILINE

语法: re.MULTILINE 或简写为 re.M

作用: 多行模式,当某字符串中有换行符\n,默认模式下是不支持换行符特性的,比如:行开头 和 行结尾,而多行模式下是支持匹配行开头的。

代码案例:

text = '这是\n一个例子'
pattern = r'^一个例子'
print('默认模式', re.findall(pattern, text))
print('多行', re.findall(pattern, text, re.M))默认模式:[]
多行:['一个例子']

正则表达式中^表示匹配行的开头,默认模式下它只能匹配字符串的开头;而在多行模式下,它还可以匹配 换行符\n后面的字符。

注意:正则语法中^匹配行开头、\A匹配字符串开头,单行模式下它两效果一致,多行模式下\A不能识别\n

四、re模块函数

re模块有12个函数,重点介绍常用模块。

1.查找一个匹配项

查找并返回一个匹配项的函数有3个:search、match、fullmatch,他们的区别分别是:

  1. search: 查找任意位置的匹配项

  2. match: 必须从字符串开头匹配

  3. fullmatch: 整个字符串与正则完全匹配

我们再来根据实际的代码案例比较:

案例1:

import re
text  = 'a这是一个例子b,这是一个例子b'
pattern = r'这是一个例子b'print('search:', re.search(pattern, text).group())
print('match:', re.match(pattern, text))
print('fullmatch: ', re.fullmatch(pattern,text))search:这是一个例子b
match:None
fullmatch:None

案例1中search函数是在字符串中任意位置匹配,只要有符合正则表达式的字符串就匹配成功,其实有两个匹配项,但search函数值返回一个。

match函数是要从头开始匹配,而字符串开头多了个字母a,所以无法匹配,fullmatch函数需要完全相同,故也不匹配!

2.查找多个匹配项

讲完查找一项,现在来看看查找多项吧,查找多项函数主要有:findall函数finditer函数

  1. findall: 从字符串任意位置查找,返回一个列表

  2. finditer:从字符串任意位置查找,返回一个迭代器

两个方法基本类似,只不过一个是返回列表,一个是返回迭代器。我们知道列表是一次性生成在内存中,而迭代器是需要使用时一点一点生成出来的,内存使用更优。

import re
text = 'a这是一个例子b,这是一个例子b'
pattern = r'这是一个例子b'
print('findall:', re.findall(pattern, text))
print('finditer:', list(re.finditer(pattern, text)))findall: ['这是一个例子b', '这是一个例子b']
finditer: [<_sre.SRE_Match object; span=(1, 8), match='这是一个例子b'>, <_sre.SRE_Match object; span=(9, 16), match='这是一个例子b'>]

如果可能存在大量的匹配项的话,建议使用finditer函数,一般情况使用findall函数基本没啥影响。

3.分割

re.split(pattern, string, maxsplit=0, flags=0) 函数:用 pattern 分开 string , maxsplit表示最多进行分割次数, flags表示模式,就是上面我们讲解的常量!

import re
text = 'a这是一个例子b,这是一个例子b'
pattern = r','
print('split: ', re.split(pattern,text,maxsplit=1,flags=re.I))split:  ['a这是一个例子b', '这是一个例子b']

注意:str模块也有一个 split函数 ,那这两个函数该怎么选呢? str.split函数功能简单,不支持正则分割,而re.split支持正则。

关于二者的速度如何? 在 不需要正则支持 且 数据量和数次不多 的情况下使用str.split函数更合适,反之则使用re.split函数。

4.替换

替换主要有sub函数subn函数,他们功能类似!

先来看看sub函数的用法:

re.sub(pattern, repl, string, count=0, flags=0) 函数参数讲解:repl替换掉string中被pattern匹配的字符, count表示最大替换次数,flags表示正则表达式的常量。

值得注意的是:sub函数中的入参:repl替换内容既可以是字符串,也可以是一个函数哦! 如果repl为函数时,只能有一个入参:Match匹配对象。

re.subn(pattern, repl, string, count=0, flags=0) 函数与 re.sub函数 功能一致,只不过返回一个元组 (字符串, 替换次数)。

5.编译正则对象

compile函数template函数 将正则表达式的样式编译为一个 正则表达式对象 (正则对象Pattern),这个对象与re模块有同样的正则函数(后面我们会讲解Pattern正则对象)。

import re
text = 'a这是一个例子b,这是一个例子b'
pattern = r'这是一个例子b'
pattern_obj = re.compile(pattern)
# 查找任意位置
print('search:', pattern_obj.search(text).group())search: 这是一个例子b

template函数compile函数 类似,只不过是增加了我们之前说的re.TEMPLATE 模式

五、正则对象Pattern

1. 与re模块 函数一致

.在re模块的函数中有一个重要的函数 compile函数 ,这个函数可以预编译返回一个正则对象,此正则对象拥有与re模块相同的函数.

既然是一致的,那到底该用re模块 还是 正则对象Pattern

而且,有些同学可能看过re模块的源码,你会发现其实compile函数 与 其他 re函数(search、split、sub等等) 内部调用的是同一个函数,最终还是调用正则对象的函数!

就是以下两种代码的底层实现是一致的:

# re函数

re.search(pattern, text)

# 正则对象函数

compile = re.compile(pattern)

compile.search(text)

官方文档推荐:在多次使用某个正则表达式时推荐使用正则对象Pattern 以增加复用性,因为通过 re.compile(pattern) 编译后的模块级函数会被缓存!

六、注意事项

1.字节串 与 字符串

模式和被搜索的字符串既可以是Unicode字符串(str),也可以是8位字节串(bytes)。但是,两者不能混用!

2.r 的作用

正则表达式使用反斜杠('')来表示特殊形式,或者把特殊字符转义成普通字符。

而反斜杠在普通的 Python 字符串里也有相同的作用,所以就产生了冲突。

解决办法是对于正则表达式样式使用 Python 的原始字符串表示法;在带有 'r' 前缀的字符串字面值中,反斜杠不必做任何特殊处理。

3.正则查找函数 返回匹配对象

查找一个匹配项(search、match、fullmatch)的函数返回值都是一个匹配对象Match,需要通过match.group()获取匹配值。

match.group()和match.groups()也是有区别的。

4.重复使用某个正则

如果要重复使用某个正则表达式,推荐使用re.compile(pattern)函数返回一个正则对象。

七、re.compile、re.match及re.search函数用法详解

参考   https://www.jb51.net/article/141830.htm

1、re.compile() 函数

编译正则表达式模式,返回一个对象。可以把常用的正则表达式编译成正则表达式对象,方便后续调用及提高效率。

re.compile(pattern, flags=0)

  • pattern 指定编译时的表达式字符串
  • flags 编译标志位,用来修改正则表达式的匹配方式。支持 re.L|re.M 同时匹配

flags 标志位参数

re.I(re.IGNORECASE)
使匹配对大小写不敏感

re.L(re.LOCAL) 
做本地化识别(locale-aware)匹配

re.M(re.MULTILINE) 
多行匹配,影响 ^ 和 $

re.S(re.DOTALL)
使 . 匹配包括换行在内的所有字符

re.U(re.UNICODE)
根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.

re.X(re.VERBOSE)
该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。

示例:

1

2

3

4

5

6

7

import re

content = 'Citizen wang , always fall in love with neighbour,WANG'

rr = re.compile(r'wan\w', re.I) # 不区分大小写

print(type(rr))

a = rr.findall(content)

print(type(a))

print(a)

findall 返回的是一个 list 对象

<class '_sre.SRE_Pattern'>
<class 'list'>
['wang', 'WANG']

2、re.match() 函数

总是从字符串‘开头曲匹配',并返回匹配的字符串的 match 对象 <class '_sre.SRE_Match'>。

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

  • pattern 匹配模式,由 re.compile 获得
  • string 需要匹配的字符串

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

import re

pattern = re.compile(r'hello')

a = re.match(pattern, 'hello world')

b = re.match(pattern, 'world hello')

c = re.match(pattern, 'hell')

d = re.match(pattern, 'hello ')

if a:

  print(a.group())

else:

  print('a 失败')

if b:

  print(b.group())

else:

  print('b 失败')

if c:

  print(c.group())

else:

  print('c 失败')

if d:

  print(d.group())

else:

  print('d 失败')

hello
b 失败
c 失败
hello

match 的方法和属性

参考链接

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

import re

str = 'hello world! hello python'

pattern = re.compile(r'(?P<first>hell\w)(?P<symbol>\s)(?P<last>.*ld!)') # 分组,0 组是整个 hello world!, 1组 hello,2组 ld!

match = re.match(pattern, str)

print('group 0:', match.group(0)) # 匹配 0 组,整个字符串

print('group 1:', match.group(1)) # 匹配第一组,hello

print('group 2:', match.group(2)) # 匹配第二组,空格

print('group 3:', match.group(3)) # 匹配第三组,ld!

print('groups:', match.groups())  # groups 方法,返回一个包含所有分组匹配的元组

print('start 0:', match.start(0), 'end 0:', match.end(0)) # 整个匹配开始和结束的索引值

print('start 1:', match.start(1), 'end 1:', match.end(1)) # 第一组开始和结束的索引值

print('start 2:', match.start(1), 'end 2:', match.end(2)) # 第二组开始和结束的索引值

print('pos 开始于:', match.pos)

print('endpos 结束于:', match.endpos) # string 的长度

print('lastgroup 最后一个被捕获的分组的名字:', match.lastgroup)

print('lastindex 最后一个分组在文本中的索引:', match.lastindex)

print('string 匹配时候使用的文本:', match.string)

print('re 匹配时候使用的 Pattern 对象:', match.re)

print('span 返回分组匹配的 index (start(group),end(group)):', match.span(2))

返回结果:

group 0: hello world!
group 1: hello
group 2: 
group 3: world!
groups: ('hello', ' ', 'world!')
start 0: 0 end 0: 12
start 1: 0 end 1: 5
start 2: 0 end 2: 6
pos 开始于: 0
endpos 结束于: 25
lastgroup 最后一个被捕获的分组的名字: last
lastindex 最后一个分组在文本中的索引: 3
string 匹配时候使用的文本: hello world! hello python
re 匹配时候使用的 Pattern 对象: re.compile('(?P<first>hell\\w)(?P<symbol>\\s)(?P<last>.*ld!)')
span 返回分组匹配的 index (start(group),end(group)): (5, 6)

3、re.search 函数

对整个字符串进行搜索匹配,返回第一个匹配的字符串的 match 对象。

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

  • pattern 匹配模式,由 re.compile 获得
  • string 需要匹配的字符串

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

import re

str = 'say hello world! hello python'

pattern = re.compile(r'(?P<first>hell\w)(?P<symbol>\s)(?P<last>.*ld!)') # 分组,0 组是整个 hello world!, 1组 hello,2组 ld!

search = re.search(pattern, str)

print('group 0:', search.group(0)) # 匹配 0 组,整个字符串

print('group 1:', search.group(1)) # 匹配第一组,hello

print('group 2:', search.group(2)) # 匹配第二组,空格

print('group 3:', search.group(3)) # 匹配第三组,ld!

print('groups:', search.groups())  # groups 方法,返回一个包含所有分组匹配的元组

print('start 0:', search.start(0), 'end 0:', search.end(0)) # 整个匹配开始和结束的索引值

print('start 1:', search.start(1), 'end 1:', search.end(1)) # 第一组开始和结束的索引值

print('start 2:', search.start(1), 'end 2:', search.end(2)) # 第二组开始和结束的索引值

print('pos 开始于:', search.pos)

print('endpos 结束于:', search.endpos) # string 的长度

print('lastgroup 最后一个被捕获的分组的名字:', search.lastgroup)

print('lastindex 最后一个分组在文本中的索引:', search.lastindex)

print('string 匹配时候使用的文本:', search.string)

print('re 匹配时候使用的 Pattern 对象:', search.re)

print('span 返回分组匹配的 index (start(group),end(group)):', search.span(2))

注意 re.search 和 re.match 匹配的 str 的区别

打印结果:

group 0: hello world!
group 1: hello
group 2: 
group 3: world!
groups: ('hello', ' ', 'world!')
start 0: 4 end 0: 16
start 1: 4 end 1: 9
start 2: 4 end 2: 10
pos 开始于: 0
endpos 结束于: 29
lastgroup 最后一个被捕获的分组的名字: last
lastindex 最后一个分组在文本中的索引: 3
string 匹配时候使用的文本: say hello world! hello python
re 匹配时候使用的 Pattern 对象: re.compile('(?P<first>hell\\w)(?P<symbol>\\s)(?P<last>.*ld!)')
span 返回分组匹配的 index (start(group),end(group)): (9, 10)

八、一些简单应用

1、识别网页文本信息中的公网安 备案号

示例:沪公网备标识31011202007523
           闽公网安备35020302000108号
           京公网安备11010502026042

分析:【前边一个字是每个省的简称】+【公网安备,还可能有 标识】+【数字特征】+【可能有 号】

import re
pattern = re.compile("[京津晋冀蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼渝川贵云藏陕甘青宁新]公网安['标识','备','证']\s*\d{10,15}号?")
number = pattern.findall(col)

2、匹配某两个字符之间的信息

示例:提取gene_name信息:

Gene_id=XLOC_003495;Gene_name=linc-DTHD1-11;Tr...
reee = re.search(r'[g|G]ene_name.+?;', xxx, flags=0, )
reee.group()[:-1] if reee else None

3、匹配电话号码

import re
phone = "2004-959-559 # 这是一个电话号码"
# 删除注释
num = re.sub(r'#.*$', "", phone)
print ("电话号码 : ", num)   # 电话号码 :  2004-959-559 # 移除非数字的内容
num = re.sub(r'\D', "", phone)
print ("电话号码 : ", num)

参考文献:https://segmentfault.com/a/1190000022242427

正则表达式介绍+一些简单应用相关推荐

  1. 基础正则表达式介绍与练习

    基础正则表达式介绍与练习 一.什么是正则表达式 在做文字处理或编写程序时,用到查找.替换等功能,使用正则表达式能够简单快捷的完成目标.简单而言,正则表达式通过一些特殊符号的帮助,使用户可以轻松快捷的完 ...

  2. 【MSDN】正则表达式介绍

    原文链接:https://msdn.microsoft.com/zh-cn/library/28hw3sce(v=vs.100).aspx Table Of Contents 正则表达式的用途 创建正 ...

  3. 由浅入深的正则表达式教程,简单快速学习正则

    文章目录 前言 正则表达式是什么 字符串匹配方法 match() 字符串检查方法 test() 正则表达式语法 ^ 和 $ 的用法和区别详解 限定符 普通字符 特殊字符 元字符 运算符优先级 常用的正 ...

  4. Matplotlib的介绍及简单操作

    Matplotlib的介绍及简单操作 1 什么是Matplotlib 是专门用于开发2D图表(包括3D图表) 以渐进.交互式方式实现数据可视化 2 为什么要学习Matplotlib 可视化是在整个数据 ...

  5. (三)AJAX基本介绍和简单实例03

    (三)AJAX基本介绍和简单实例03-----Ajax与数据库的动态应用 前台显示界面: 选择所有客户之后: 选择其中一个客户---杜森: Demo03.html代码 <html> < ...

  6. rabbitMQ消息队列 – 面板介绍及简单demo

    首先rabbit安装好之后,运维会给一个控制面板. 默认账号密码为guest 登入以后可以看到具体界面. 在此鸣谢百度翻译给予的大力支持.. ###写一个简单的demo 编写之前..虽然说可以直接用底 ...

  7. Protobuf介绍及简单使用(上)

    目录 Protobuf 介绍 优势 protobuf语法 Specifying Field Rules Data type Data name Number Protobuf注释 保留字段与标识符 s ...

  8. SQL Server中追踪器Trace的介绍和简单使用

    原文:SQL Server中追踪器Trace的介绍和简单使用 一.What is Trace? 对于SQL Profiler这个工具相信大家都不是很陌生,没用过的朋友可以在SQL Server Man ...

  9. S3C2440移植linux3.4.2内核之内核框架介绍及简单修改

    文章目录 uboot启动内核分析 简单配置内核 编译内核 设置机器ID 修改晶振 移植Linux3.4.2内核其他文章链接: S3C2440移植linux3.4.2内核之内核框架介绍及简单修改 S3C ...

最新文章

  1. Python:模拟登录、点击和执行 JavaScript 语句案例
  2. 习题8_6与习题9_2
  3. ControlButton按钮事件
  4. 小甲鱼-累加数据段中的前3个字型数据【不对的话,请指教!】
  5. 当前工作目录Python
  6. P6810 「MCOI-02」Convex Hull 凸包
  7. Little Alchemy 游戏 - 扒答案。。 Java
  8. linux使用jinja2模板_linux下安装python组件之jinja2
  9. vbm 分析_VBM
  10. 双系统时间不一致问题
  11. Hexo 搭建个人博客学习笔记(4):个性化主题Next个性化配置
  12. 《编程的原则:改善代码质量的101个方法》读书笔记
  13. 请教苹果虚拟机自动配置序列号ID脚本
  14. R语言计算回归模型R方(R-Squared)实战
  15. IOS APP 推荐
  16. 【180622】VC++不规则窗体编程跳棋游戏实例
  17. 《ucore lab1 exercise5》实验报告
  18. 亚马逊云服务器使用密码登录
  19. Unity3D --对撞机/碰撞器 介绍
  20. 苹果电脑拷贝文件到u盘很慢_ChronoSync v4.9.1 一款文件资料数据云同步备份工具...

热门文章

  1. 软件开发十三种文档格式
  2. 手机中android版本9是什么,这是Android手机Android 9.0还是Android 6.0?
  3. 黑苹果安装后不能启动Windows解决
  4. 常用工具 [ubuntu 图像编辑软件]
  5. r语言python0基础_万丈高楼平地起,从零开始学R语(生信分析向,R语言基础)...
  6. 腾讯云神笔低代码平台的申请没通过,只能等公测了
  7. c语言直接输出PDF,C语言格式化输出总结.pdf
  8. 恶趣味程序之《徒有其表》
  9. 一次进入 Cisco Router(SDM)小记
  10. 高精度加法 problem A+B