Python3标准库(二) re模块
正则表达式(Regular Expression)是字符串处理的常用工具,通常被用来检索、替换那些符合某个模式(Pattern)的文本。很多程序设计语言都支持正则表达式,像Perl、Java、C/C++。在 Python 中是通过标准库中的re 模块 提供对正则的支持。
一、正则表达式介绍
在使用 re 模块之前,先来了解一下正则表达式的基本语法。
1)用途
通过使用正则表达式,可以:
测试字符串内的模式。—— 例如,可以测试输入字符串,以查看字符串内是否出现电话号码模式或信用卡号码模式。这称为数据验证。
替换文本。—— 可以使用正则表达式来识别文档中的特定文本,完全删除该文本或者用其他文本替换它。
基于模式匹配从字符串中提取子字符串。—— 可以查找文档内或输入域内特定的文本。
2)语法
本文主要介绍正则的基本语法以及 re 模块的使用,不包括如何编写高效的正则表达式、如何优化正则表达式,这些主题请看其他教程。
下图列出了Python支持的一些正则表达式元字符和语法:
3)贪婪模式与非贪婪模式
“贪婪模式”总是尝试匹配尽可能多的字符;“非贪婪模式”则相反,总是匹配尽可能少的字符。例如,用"ab*"如果用于查找"abbbc",将找到"abbb"。而如果使用非贪婪的数量词"ab*?",将找到"a"。
二、使用 re 模块
下面我们开始来使用 re 模块。
1)编译正则表达式
re 模块提供了 re.compile() 函数将一个字符串编译成 pattern object,用于匹配或搜索。函数原型如下:
re.compile(pattern, flags=0)
re.compile() 还接受一个可选的参数 flag,用于指定正则匹配的模式。关于匹配模式,后面将会讲到。
p = re.compile('ab*', re.IGNORECASE)
2)反斜杠的困扰
在 python 的字符串中,\ 是被当做转义字符的。在正则表达式中,\ 也是被当做转义字符。这就导致了一个问题:如果你要匹配 \ 字符串,那么传递给 re.compile() 的字符串必须是"\\\\"。
由于字符串的转义,所以实际传递给 re.compile() 的是"\\",然后再通过正则表达式的转义,"\\" 会匹配到字符"\"。这样虽然可以正确匹配到字符 \,但是很麻烦,而且容易漏写反斜杠而导致 Bug。那么有什么好的解决方案呢?
原始字符串很好的解决了这个问题,通过在字符串前面添加一个r,表示原始字符串,不让字符串的反斜杠发生转义。那么就可以使用r"\\"
来匹配字符\
了。
3)pattern object 执行匹配
一旦你编译得到了一个 pattern object,你就可以使用 pattern object 的方法或属性进行匹配了,下面列举几个常用的方法,更多请看这里。
regex.match(string[, pos[, endpos]])
:
- 匹配从 pos 到 endpos 的字符子串的开头。匹配成功返回一个 match object,不匹配返回 None。
- pos 的默认值是0,endpos 的默认值是 len(string),所以默认情况下是匹配整个字符串的开头。
import re
pattern = re.compile("ar{1}")
print(pattern.match("army")) # "ar"在开头,匹配成功
print(pattern.match("mary")) # "ar"不在开头,匹配失败
print(pattern.match("mary", 1)) # "ar"不在开头,但在子串的开头 # 输出结果:
# <_sre.SRE_Match object; span=(0, 2), match='ar'>
# None
# <_sre.SRE_Match object; span=(1, 3), match='ar'>
regex.search(string[, pos[, endpos]])
:
- 扫描整个字符串,并返回它找到的第一个匹配(Match object)。
- 和 regex.match() 一样,可以通过 pos 和 endpos 指定范围。
pattern = re.compile("ar{1}")
match = pattern.search("mary") # search
print(match) # 输出结果:
# <_sre.SRE_Match object; span=(1, 3), match='ar'>
regex.findall(string[, pos[, endpos]])
:
- 找到所有匹配的子串,并返回一个 list 。
- 可选参数 pos 和 endpos 和上面一样。
pattern = re.compile(r"\d+")
lst = pattern.findall("abc1def2rst3xyz") # findall
print(lst) # 输出结果:
# ['1', '2', '3']
regex.finditer(string[, pos[, endpos]])
:
- 找到所有匹配的子串,并返回由这些匹配结果(match object)组成的迭代器。
- 可选参数 pos 和 endpos 和上面一样。
pattern = re.compile(r"\d+")
p = pattern.finditer("abc1def2rst3xyz")
for i in p:
print(i) # 输出结果:
# <_sre.SRE_Match object; span=(3, 4), match='1'>
# <_sre.SRE_Match object; span=(7, 8), match='2'>
# <_sre.SRE_Match object; span=(11, 12), match='3'>
4)match object 获取结果
在上面讲到,通过 pattern object 的方法(除 findall 外)进行匹配得到的返回结果都是
match object。每一个 match object 都包含了匹配到的相关信息,比如,起始位置、匹配到的子串。那么,我们如何从 match object 中提取这些信息呢?
match object 提供了一些方法,下面列举几个常用的方法,更多请看这里。
- 返回 match object 中的字符串。
- 每一个 ( ) 都是一个分组,分组编号从1开始,从左往右,每遇到一个左括号,分组编号+1。
- 组 0 总是存在的,它就是整个表达式 。
- 没有参数时,group1默认为0,这时返回整个匹配到的字符串。
- 指定一个参数(整数)时,返回该分组匹配到的字符串。
- 指定多个参数时,返回由那几个分组匹配到的字符串组成的 tuple。
pattern = re.compile(r"(\w+) (\w+)")
m = pattern.match("Kobe Bryant, Lakers")
print(m) # <_sre.SRE_Match object; span=(0, 11), match='Kobe Bryant'>
print(m.group()) # Kobe Bryant
print(m.group(1)) # Kobe
print(m.group(2)) # Bryant
print(m.group(1, 2)) # ('Kobe', 'Bryant')
- 返回由所有分组匹配到的字符串组成的 tuple。
>>> m = re.match(r"(\d+)\.(\d+)", "24.1632")
>>> m.groups()
('24', '1632')
- 没有参数时,返回匹配到的字符串的起始位置。
- 指定参数(整数)时,返回该分组匹配到的字符串的起始位置。
pattern = re.compile(r"(\w+) (\w+)")
m = pattern.match("Kobe Bryant, Lakers")
print(m.start()) # 0
print(m.start(2)) # 5
- 没有参数时,返回匹配到的字符串的结束位置。
- 指定参数(整数)时,返回该分组匹配到的字符串的结束位置。
pattern = re.compile(r"(\w+) (\w+)")
m = pattern.match("Kobe Bryant, Lakers")
print(m.end()) # 11
print(m.end(1)) # 4
- 返回一个二元 tuple 表示匹配到的字符串的范围,即 (start, end)。
- 指定参数时,返回该分组匹配到的字符串的 (start, end)。
pattern = re.compile(r"(\w+) (\w+)")
m = pattern.match("Kobe Bryant, Lakers")
print(m.span()) # (0, 11)
print(m.span(2)) # (5, 11)
5)模块级别的函数
上面讲到的函数都是对象的方法,要使用它们必须先得到相应的对象。本节将介绍一些Module-Level Functions,比如 match(),search(),findall() 等等。你不需要创建一个 pattern object 就可以直接调用这些函数。
re.compile(pattern, flags=0)
:上面已经介绍过。
re.match(pattern, string, flags=0)
:
pattern = re.compile(r"(\w+) (\w+)")
m = pattern.match("Kobe Bryant, Lakers")
# 相当于
m = re.match(r"(\w+) (\w+)","Kobe Bryant, Lakers")
re.search(pattern, string, flags=0)
:
pattern = re.compile(r"(\w+) (\w+)")
m = pattern.search("Kobe Bryant, Lakers")
# 相当于
m = re.search(r"(\w+) (\w+)","Kobe Bryant, Lakers")
re.findall(pattern, string, flags=0)
:与上面类似。
re.finditer(pattern, string, flags=0)
:与上面类似。
6)编译标志(匹配模式)
在讲 re.compile() 函数时,曾说到该函数还接受可选的第二个参数,用以设置匹配模式。可选的匹配模式有:
re.IGNORECASE:忽略大小写,同 re.I。
re.MULTILINE:多行模式,改变^和$的行为,同 re.M。
re.DOTALL:点任意匹配模式,让'.'可以匹配包括'\n'在内的任意字符,同 re.S。
re.LOCALE:使预定字符类 \w \W \b \B \s \S 取决于当前区域设定, 同 re.L。
re.ASCII:使 \w \W \b \B \s \S 只匹配 ASCII 字符,而不是 Unicode 字符,同
re.A。re.VERBOSE:详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释。主要是为了让正则表达式更易读,同re.X。例如,以下两个正则表达式是等价的:
a = re.compile(r"""\d + # the integral part
\. # the decimal point
\d * # some fractional digits""", re.X)
b = re.compile(r"\d+\.\d*")
三、修改字符串
第二部分讲的是字符串的匹配和搜索,但是并没有改变字符串。下面就讲一下可以改变字符串的操作。
1)分割字符串
split()
函数在匹配的地方将字符串分割,并返回一个 list。同样的,re 模块提供了两种 split 函数,一个是 pattern object 的方法,一个是模块级的函数。
regex.split(string, maxsplit=0)
:
- maxsplit用于指定最大分割次数,不指定将全部分割。
pattern = re.compile(r"[A-Z]+")
m = pattern.split("abcDefgHijkLmnoPqrs")
print(m) # 输出结果:
# ['abc', 'efg', 'ijk', 'mno', 'qrs']
re.split(pattern, string, maxsplit=0, flags=0)
:
- 模块级函数,功能与 regex.split() 相同。
- flags用于指定匹配模式。
m = re.split(r"[A-Z]+","abcDefgHijkLmnoPqrs")
print(m) # 输出结果:
# ['abc', 'efg', 'ijk', 'mno', 'qrs']
2)搜索与替换
另一个常用的功能是找到所有的匹配,并把它们用不同的字符串替换。re 模块提供了sub()
和subn()
来实现替换的功能,而它们也分别有自己两个不同版本的函数。
regex.sub(repl, string, count=0)
:
- 使用 repl 替换 string 中每一个匹配的子串,返回替换后的字符串。若找不到匹配,则返回原字符串。
- repl 可以是一个字符串,也可以是一个函数。
- 当repl是一个字符串时,任何在其中的反斜杠都会被处理。
- 当repl是一个函数时,这个函数应当只接受一个参数(Match对象),并返回一个字符串用于替换。
- count 用于指定最多替换次数,不指定时全部替换。
def fun(m):
return m.group().upper() pattern = re.compile(r"like", re.I)
s1 = pattern.sub(r"love", "I like you, do you like me?")
s2 = pattern.sub(fun, "I like you, do you like me?")
print(s1)
print(s2) # 输出结果:
# I love you, do you love me?
# I LIKE you, do you LIKE me?
re.sub(pattern, repl, string, count=0, flags=0)
:
- 模块级函数,与 regex.sub() 函数功能相同。
- flags 用于指定匹配模式。
regex.subn(repl, string, count=0)
:
- 同 sub(),只不过返回值是一个二元 tuple,即
(sub函数返回值, 替换次数)
。
re.subn(pattern, repl, string, count=0, flags=0)
:
- 模块级函数,功能同 regex.subn()。
Python3标准库(二) re模块的更多相关文章
- 7.Python3标准库--文件系统
''' Python的标准库中包含大量工具,可以处理文件系统中的文件,构造和解析文件名,还可以检查文件内容. 处理文件的第一步是要确定处理的文件的名字.Python将文件名表示为简单的字符串,另外还提 ...
- 8.Python3标准库--数据持久存储与交换
''' 持久存储数据以便长期使用包括两个方面:在对象的内存中表示和存储格式之间来回转换数据,以及处理转换后数据的存储区. 标准库包含很多模块可以处理不同情况下的这两个方面 有两个模块可以将对象转换为一 ...
- Python3 标准库
Python3标准库 更详尽:http://blog.csdn.net/jurbo/article/details/52334345 文本 string:通用字符串操作 re:正则表达式操作 diff ...
- python023 Python3 标准库概览
Python3 标准库概览 操作系统接口 os模块提供了不少与操作系统相关联的函数. >>> import os >>> os.getcwd() # 返回当前的工作 ...
- python3标准库总结
Python3标准库 操作系统接口 os模块提供了不少与操作系统相关联的函数. ? 1 2 3 4 5 6 >>> import os >>> os.getcwd( ...
- python常用标准库(时间模块 time和datetime)
常用的标准库 time时间模块 import time time -- 获取本地时间戳 时间戳又被称之为是Unix时间戳,原本是在Unix系统中的计时工具. 它的含义是从1970年1月1日(UTC/G ...
- (转)python标准库中socket模块详解
python标准库中socket模块详解 socket模块简介 原文:http://www.lybbn.cn/data/datas.php?yw=71 网络上的两个程序通过一个双向的通信连接实现数据的 ...
- 1.Python3标准库--前戏
Python有一个很大的优势便是在于其拥有丰富的第三方库,可以解决很多很多问题.其实Python的标准库也是非常丰富的,今后我将介绍一下Python的标准库. 这个教程使用的书籍就叫做<Pyth ...
- 比较两个文件的异同Python3 标准库difflib 实现
比较两个文件的异同Python3 标准库difflib 实现 对于要比较两个文件特别是配置文件的差异,这种需求很常见,如果用眼睛看,真是眼睛疼. 可以使用linux命令行工具diff a_file b ...
- python——模块、标准库、第三方模块安装
模块(module)简介 模块化--指将一个完整的程序分解为一个一个小的模块,通过将模块组合,来搭建出一个完整的程序. 模块化的特点: ① 方便开发 ② 方便维护 ③ 模块可以复用! 在Python中 ...
随机推荐
- MySQL for Mac 终端操作说明
mysql for mac 终端操作说明MySQL服务开启Mac版mysql可以从设置里启动服务: 如果想要在终端(Terminal)中操作mysql,需要先添加mysql路径,在此以zsh为例: # ...
- 5-Java-C(调和级数)
题目描述: 1/1 + 1/2 + 1/3 + 1/4 + ... 在数学上称为调和级数. 它是发散的,也就是说,只要加上足够多的项,就可以得到任意大的数字. 但是,它发散的很慢: 前1项和达到 1. ...
- call, apply, bind 区别
#call, apply, bind 区别及模拟实现call apply bind 三者都可以用来改变this的指向,但是在用法上略有不同 首先说一下call和apply的区别 call和apply ...
- 边框带阴影 box-shadow
.chosen-container-active .chosen-single { border: 1px solid #5897fb; -webkit-box-shadow: 0 0 5px rgb ...
- seq2seq(1)- EncoderDecoder架构
零 seq2seq是从序列到序列的学习过程,最重要的是输入序列和输出序列是可变长的,这种方式就非常灵活了,典型的机器翻译就是这样一个过程. 一 最基本的seq2seq网络架构如下所示: 可以看到,en ...
- 查看密码存放地-shadow
shadow 位置:/cat/shadow 作用:存放用户的密码等信息 使用查看命令以后得到以下数据 我们会看到9个字段,分别用 :隔开,如上图所示一一解释: 第一字段:用户名称 第二字段:加密密码 ...
- mysql负载均衡
一.docker安装haproxy:docker pull haproxy 二.配置haproxy(参考url:https://zhangge.net/5125.html),vim /usr/loca ...
- JAVA加载Properties配置资源文件
JAVA加载Properties配置资源文件 制作人:全心全意 配置文件(资源文件):以properties作为拓展名的文件 Java代码是如何加载properties文件的? 必须使用Propert ...
- BNUOJ 1589 Closest Common Ancestors
Closest Common Ancestors Time Limit: 2000ms Memory Limit: 10000KB This problem will be judged on PKU ...
- 通过setContentView设置activity的不同样式
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle saved ...