Python:正则表达式概念
#正则表达式内容非常多,网上的学习资源也是目不暇接,我从中筛选学习并且整理出以下 的学习笔记
一、正则表达式匹配过程:
1.依次拿出表达式和文本中的字符比较
2.如果每一个字符都能匹配,则匹配成功;一旦有匹配不成功的字符则匹配失败
3.如果表达式中有量词或边界,这个过程会稍微有一些不同
二、语法规则
在正则表达式中,如果直接给出字符,就是精确匹配。
用\d
可以匹配一个数字,\w
可以匹配一个字母或数字,所以:
- '00\d'可以匹配'007',但无法匹配'00A';
- '\d\d\d'可以匹配'010';
- '\w\w\d'可以匹配'py3';
.
可以匹配任意字符,所以:
- 'py.'可以匹配'pyc'、'pyo'、'py!'等等。
要匹配变长的字符,在正则表达式中,用*
表示任意个字符(包括0个),用+
表示至少一个字符,用?
表示0个或1个字符,用{n}
表示n个字符,用{n,m}
表示n-m个字符:
来看一个复杂的栗子:\d{3}\s+\d{3,8}
。
- \d{3}表示匹配3个数字,例如'010';
- \s可以匹配一个空格(也包括Tab等空白符),所以\s+表示至少有一个空格,例如匹配' ',' '等;
- \d{3,8}表示3-8个数字,例如'1234567'。
综合起来,上面的正则表达式可以匹配以任意个空格隔开的带区号的电话号码。
如果要匹配'010-12345'
这样的号码呢?由于'-'
是特殊字符,在正则表达式中,要用'\'
转义,所以,上面的正则是\d{3}\-\d{3,8}
。
但是,仍然无法匹配'010 - 12345'
,因为带有空格。所以我们需要更复杂的匹配方式。
要做更精确地匹配,可以用[]
表示范围,比如:
- [0-9a-zA-Z\_]可以匹配一个数字、字母或者下划线;
- [0-9a-zA-Z\_]+可以匹配至少由一个数字、字母或者下划线组成的字符串,比如'a100','0_Z','Py3000'等等;
- [a-zA-Z\_][0-9a-zA-Z\_]*可以匹配由字母或下划线开头,后接任意个由一个数字、字母或者下划线组成的字符串,也就是Python合法的变量;
- [a-zA-Z\_][0-9a-zA-Z\_]{0, 19}更精确地限制了变量的长度是1-20个字符(前面1个字符+后面最多19个字符)。
A|B
可以匹配A或B,所以(P|p)ython
可以匹配'Python'
或者'python'
。
^
表示行的开头,^\d
表示必须以数字开头。
$
表示行的结束,\d$
表示必须以数字结束。
例如:py
也可以匹配'python'
,但是加上^py$
就变成了整行匹配,就只能匹配'py'
了。
三、正则表达式相关注解
1.数量词 * + ?{}等的贪婪模式和费贪婪模式
正则匹配默认是贪婪匹配,也就是匹配尽可能多的字符。举例如下,匹配出数字后面的0
:
>>> re.match(r'^(\d+)(0*)$', '').groups()
('', '')
由于\d+
采用贪婪匹配,直接把后面的0
全部匹配了,结果0*
只能匹配空字符串了。
必须让\d+
采用非贪婪匹配(也就是尽可能少匹配),才能把后面的0
匹配出来,加个?
就可以让\d+
采用非贪婪匹配:
>>> re.match(r'^(\d+?)(0*)$', '').groups()
('', '')
注:我们一般使用非贪婪模式来提取
2.反斜杠问题
正则表达式里使用”\”作为转义字符,这就可能造成反斜杠困扰。Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r”\\”表示。同样,匹配一个数字的”\\d”可以写成r”\d”。
四、re模块
#返回pattern对象
re.compile(string[,flag])
#以下为匹配所用函数
re.match(pattern, string[, flags])
re.search(pattern, string[, flags])
re.split(pattern, string[, maxsplit])
re.findall(pattern, string[, flags])
re.finditer(pattern, string[, flags])
re.sub(pattern, repl, string[, count])
re.subn(pattern, repl, string[, count])
pattern可以理解为一个匹配模式,那么我们怎么获得这个匹配模式呢?很简单,我们需要利用re.compile方法就可以。例如
pattern = re.compile(r'hello')
在参数中我们传入了原生字符串对象,通过compile方法编译生成一个pattern对象,然后我们利用这个对象来进行进一步的匹配。
#以下介绍是否使用compile的情况
1. 使用re.compile
re模块中包含一个重要函数是compile(pattern [, flags]) ,该函数根据包含的正则表达式的字符串创建模式对象。可以实现更有效率的匹配。在直接使用字符串表示的正则表达式进行search,match和findall操作时,python会将字符串转换为正则表达式对象。而使用compile完成一次转换之后,在每次使用模式的时候就不用重复转换。当然,使用re.compile()函数进行转换后,re.search(pattern, string)的调用方式就转换为 pattern.search(string)的调用方式。
其中,后一种调用方式中,pattern是用compile创建的模式对象。如下:
>>> import re
>>> some_text = 'a,b,,,,c d'
>>> reObj = re.compile('[, ]+')
>>> reObj.split(some_text)
['a', 'b', 'c', 'd']
2.不使用re.compile
在进行search,match等操作前不适用compile函数,会导致重复使用模式时,需要对模式进行重复的转换。降低匹配速度。而此种方法的调用方式,更为直观。如下:
>>> import re
>>> some_text = 'a,b,,,,c d'
>>> re.split('[, ]+',some_text)
['a', 'b', 'c', 'd']
(1)re.match(pattern, string[, flags])
这个方法将会从string(我们要匹配的字符串)的开头开始,尝试匹配pattern,一直向后匹配,如果遇到无法匹配的字符,立即返回 None,如果匹配未结束已经到达string的末尾,也会返回None。两个结果均表示匹配失败,否则匹配pattern成功,同时匹配终止,不再对 string向后匹配。
# -*- coding: utf-8 -*- #导入re模块
import re # 将正则表达式编译成Pattern对象,注意hello前面的r的意思是“原生字符串”
pattern = re.compile(r'hello') # 使用re.match匹配文本,获得匹配结果,无法匹配时将返回None
result1 = re.match(pattern,'hello')
result2 = re.match(pattern,'helloo CQC!')
result3 = re.match(pattern,'helo CQC!')
result4 = re.match(pattern,'hello CQC!') #如果1匹配成功
if result1:
# 使用Match获得分组信息
print result1.group()
else:
print '1匹配失败!' #如果2匹配成功
if result2:
# 使用Match获得分组信息
print result2.group()
else:
print '2匹配失败!' #如果3匹配成功
if result3:
# 使用Match获得分组信息
print result3.group()
else:
print '3匹配失败!' #如果4匹配成功
if result4:
# 使用Match获得分组信息
print result4.group()
else:
print '4匹配失败!' #运行结果
hello
hello
3匹配失败!
hello
#下面说明match的对象和方法
属性:
1.string: 匹配时使用的文本。
2.re: 匹配时使用的Pattern对象。
3.pos: 文本中正则表达式开始搜索的索引。值与Pattern.match()和Pattern.seach()方法的同名参数相同。
4.endpos: 文本中正则表达式结束搜索的索引。值与Pattern.match()和Pattern.seach()方法的同名参数相同。
5.lastindex: 最后一个被捕获的分组在文本中的索引。如果没有被捕获的分组,将为None。
6.lastgroup: 最后一个被捕获的分组的别名。如果这个分组没有别名或者没有被捕获的分组,将为None。
方法:
1.group([group1, …]):
获得一个或多个分组截获的字符串;指定多个参数时将以元组形式返回。group1可以使用编号也可以使用别名;编号0代表整个匹配的子串;不填写参数时,返回group(0);没有截获字符串的组返回None;截获了多次的组返回最后一次截获的子串。
2.groups([default]):
以元组形式返回全部分组截获的字符串。相当于调用group(1,2,…last)。default表示没有截获字符串的组以这个值替代,默认为None。
3.groupdict([default]):
返回以有别名的组的别名为键、以该组截获的子串为值的字典,没有别名的组不包含在内。default含义同上。
4.start([group]):
返回指定的组截获的子串在string中的起始索引(子串第一个字符的索引)。group默认值为0。
5.end([group]):
返回指定的组截获的子串在string中的结束索引(子串最后一个字符的索引+1)。group默认值为0。
6.span([group]):
返回(start(group), end(group))。
7.expand(template):
将匹配到的分组代入template中然后返回。template中可以使用\id或\g、\g引用分组,但不能使用编号0。\id与\g是等价的;但\10将被认为是第10个分组,如果你想表达\1之后是字符'0',只能使用\g0。
# -*- coding: utf-8 -*-
#一个简单的match实例 import re
# 匹配如下内容:单词+空格+单词+任意字符
m = re.match(r'(\w+) (\w+)(?P.*)', 'hello world!') print "m.string:", m.string
print "m.re:", m.re
print "m.pos:", m.pos
print "m.endpos:", m.endpos
print "m.lastindex:", m.lastindex
print "m.lastgroup:", m.lastgroup
print "m.group():", m.group()
print "m.group(1,2):", m.group(1, 2)
print "m.groups():", m.groups()
print "m.groupdict():", m.groupdict()
print "m.start(2):", m.start(2)
print "m.end(2):", m.end(2)
print "m.span(2):", m.span(2)
print r"m.expand(r'\g \g\g'):", m.expand(r'\2 \1\3') # 输出结果
# m.string: hello world!
# m.re:
# m.pos: 0
# m.endpos: 12
# m.lastindex: 3
# m.lastgroup: sign
# m.group(1,2): ('hello', 'world')
# m.groups(): ('hello', 'world', '!')
# m.groupdict(): {'sign': '!'}
# m.start(2): 6
# m.end(2): 11
# m.span(2): (6, 11)
# m.expand(r'\2 \1\3'): world hello!
(2)re.search(pattern, string[, flags])
search方法与match方法极其类似,区别在于match()函数只检测re是不是在string的开始位置匹配,search()会扫描整个string查找匹配,match()只有在0位置匹配成功的话才有返回,如果不是开始位置匹配成功的话,match()就返回None。同样,search方法的返回对象同样match()返回对象的方法和属性。
#导入re模块
import re # 将正则表达式编译成Pattern对象
pattern = re.compile(r'world')
# 使用search()查找匹配的子串,不存在能匹配的子串时将返回None
# 这个例子中使用match()无法成功匹配
match = re.search(pattern,'hello world!')
if match:
# 使用Match获得分组信息
print match.group()
# 输出结果#world
(3)re.split(pattern, string[, maxsplit])
按照能够匹配的子串将string分割后返回列表。maxsplit用于指定最大分割次数,不指定将全部分割。
import re pattern = re.compile(r'\d+')
print re.split(pattern,'one1two2three3four4') # 输出结果
# ['one', 'two', 'three', 'four', '']
(4)re.findall(pattern, string[, flags])
搜索string,以列表形式返回全部能匹配的子串。#这条应用很多
import re pattern = re.compile(r'\d+')
print re.findall(pattern,'one1two2three3four4') # 输出结果
# ['1', '2', '3', '4']
(5)re.finditer(pattern, string[, flags])
搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。
import re pattern = re.compile(r'\d+')
for m in re.finditer(pattern,'one1two2three3four4'):
print m.group(), #输出结果
# 1 2 3 4
(6)re.sub(pattern, repl, string[, count])
使用repl替换string中每一个匹配的子串后返回替换后的字符串。
当repl是一个字符串时,可以使用\id或\g、\g引用分组,但不能使用编号0。
当repl是一个方法时,这个方法应当只接受一个参数(Match对象),并返回一个字符串用于替换(返回的字符串中不能再引用分组)。
count用于指定最多替换次数,不指定时全部替换。
import re pattern = re.compile(r'(\w+) (\w+)')
s = 'i say, hello world!' print re.sub(pattern,r'\2 \1', s) def func(m):
return m.group(1).title() + ' ' + m.group(2).title() print re.sub(pattern,func, s) #输出结果
# say i, world hello!
# I Say, Hello World!
(7)re.subn(pattern, repl, string[, count])
返回 (sub(repl, string[, count]), 替换次数)。
import re pattern = re.compile(r'(\w+) (\w+)')
s = 'i say, hello world!' print re.subn(pattern,r'\2 \1', s) def func(m):
return m.group(1).title() + ' ' + m.group(2).title() print re.subn(pattern,func, s) #输出结果
# ('say i, world hello!', 2)
# ('I Say, Hello World!', 2)
学习资源来自:
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143193331387014ccd1040c814dee8b2164bb4f064cff000
http://www.jb51.net/article/65286.htm
https://www.cnblogs.com/nomorewzx/p/4203829.html
http://crossincode.com/home/
Python:正则表达式概念的更多相关文章
- Python 正则表达式入门(中级篇)
Python 正则表达式入门(中级篇) 初级篇链接:http://www.cnblogs.com/chuxiuhong/p/5885073.html 上一篇我们说在这一篇里,我们会介绍子表达式,向前向 ...
- Python 正则表达式入门(初级篇)
Python 正则表达式入门(初级篇) 本文主要为没有使用正则表达式经验的新手入门所写. 转载请写明出处 引子 首先说 正则表达式是什么? 正则表达式,又称正规表示式.正规表示法.正规表达式.规则表达 ...
- python 正则表达式汇总
一. 正则表达式基础 1.1.概念介绍 正则表达式是用于处理字符串的强大工具,它并不是Python的一部分. 其他编程语言中也有正则表达式的概念,区别只在于不同的编程语言实现支持的语法数量不同. 它拥 ...
- 转载 Python 正则表达式入门(中级篇)
Python 正则表达式入门(中级篇) 初级篇链接:http://www.cnblogs.com/chuxiuhong/p/5885073.html 上一篇我们说在这一篇里,我们会介绍子表达式,向前向 ...
- 转载 Python 正则表达式入门(初级篇)
Python 正则表达式入门(初级篇) 本文主要为没有使用正则表达式经验的新手入门所写.转载请写明出处 引子 首先说 正则表达式是什么? 正则表达式,又称正规表示式.正规表示法.正规表达式.规则表达式 ...
- python正则表达式一[转]
原文:http://blog.jobbole.com/74844/ 作为一个概念而言,正则表达式对于Python来说并不是独有的.但是,Python中的正则表达式在实际使用过程中还是有一些细小的差别. ...
- python正则表达式re模块详细介绍--转载
本模块提供了和Perl里的正则表达式类似的功能,不关是正则表达式本身还是被搜索的字符串,都可以是Unicode字符,这点不用担心,python会处理地和Ascii字符一样漂亮. 正则表达式使用反斜杆( ...
- Python正则表达式的七个使用范例-乾颐堂
作为一个概念而言,正则表达式对于Python来说并不是独有的.但是,Python中的正则表达式在实际使用过程中还是有一些细小的差别. 本文是一系列关于Python正则表达式文章的其中一部分.在这个系列 ...
- python正则表达式入门篇
文章来源于:https://www.cnblogs.com/chuxiuhong/p/5885073.html Python 正则表达式入门(初级篇) 本文主要为没有使用正则表达式经验的新手入门所写. ...
- 学会python正则表达式就是这么简单
一前言 本篇文章带大家快速入门正则表达式的使用,正则表达式的规则不仅适用python语言,基本大多数编程语言都适用,在日常使用中极为广泛,读者们有必要学好正则表达式.看完这篇文章,读者们要理解什么是正 ...
随机推荐
- 5 -- Hibernate的基本用法 --4 1 创建Configuration对象
org.hibernate.cfg.Configuration实例代表了应用程序到SQL数据库的配置信息,Configuration对象提供了一个buildSessionFactory()方法,该方法 ...
- 8 -- 深入使用Spring -- 3...3 使用Resouce作为属性
8.3.3 使用Resouce作为属性 当应用程序中的Bean实例需要访问资源时,Spring可以直接利用依赖注入. 如果Bean实例需要访问资源,有如下两种解决方案: ⊙ 在代码中获取Resourc ...
- Django SimpleCMDB API
编写一个API,当我们访问 http://192.168.216.128:8000/hostinfo/getjson 时,返回 json 格式的主机组和组成员信息: [root@localhost S ...
- Ubuntu图形界面和字符界面转换、指定默认启动界面
1.按ALT+CTRL+F1.F2.F3.F4.F5.F6.F7可来回切换7个界面(Linux实体机) 其中ALT+CTRL+F7可切换到图形界面(Linux实体机) 如果是V ...
- composer安装指定版本的laravel
composer create-project laravel/laravel blog 4.2.*
- 【cs229-Lecture7】支持向量机(SVM)
SVM不错的学习资料: 百度网盘链接: http://pan.baidu.com/s/1hqw0Rnm 密码: asec blog:http://www.blogjava.net/zhenandaci ...
- 通俗大白话来理解TCP协议的三次握手和四次分手
通俗理解: 但是为什么一定要进行三次握手来保证连接是双工的呢,一次不行么?两次不行么?我们举一个现实生活中两个人进行语言沟通的例子来模拟三次握手. 引用网上的一些通俗易懂的例子,虽然不太正确,后面会指 ...
- jQuery缓存机制(一)
1.首先看一下涉及到jQuery缓存机制的代码结构: // 定义一些jQuery内部的变量,方便后续使用 var data_user, data_priv, // 后续会被赋值为两个Data对象 rb ...
- Excel2010如何合并列数据
小编以下图的Excel数据文件为例,如下图,有两列数据,第一列是歌曲名,第二列是该歌曲的演唱者,他们是有关联呢,那么如何把他们合并到同一列呢. 首先点击第3列的开始空白格,在这里编辑公式 =a1& ...
- storm并发度理解
1. 核心原理 一个运行中的拓扑是由什么组成的:worker进程,executors和tasks.Storm是按照下面3种主要的部分来区分Storm集群中一个实际运行的拓扑的:Worker进程.Exe ...