Python RE 正则表达式模块

通用字符匹配

语法 通配符匹配作用解析
. 匹配除换行符之外的任意一个字符
* 匹配前一个字符出现零次或任意多次
+ 匹配前一个字符出现1次或任意多次
? 匹配前一个字符出现1次或0次
^ 匹配以指定字符开头的数据
$ 匹配以指定字符结尾的数据
{m} 匹配前一个字符出现过m次的记录
{n,m} 匹配前一个字符,最少出现n次,最多出现m次

匹配任意一个字符(.) 默认匹配除\n之外的任意一个字符,若指定flag=DOTALL则匹配包括换行在内的字符.

>>> re.search("hel.o","hello lyshark,hello world").group()
'hello'

>>> re.findall("hel.o","hello lyshark hello world")
['hello','hello']

匹配前一个字符出现0至任意多次(*) 匹配星号前面的字符出现0次,或任意多次.

>>> re.findall("ab*","abccba23acbcabb")
['ab','a','abb']

匹配前一个字符出现1次或任意多次(+) 匹配加号前面的字符出现过1次,或任意多次,至少出现一次.

>>> re.findall("ab+",'abb']

匹配前一个字符出现1次或0次(?) 匹配前一个字符出现过1次或0次,允许出现0次.

>>> re.findall("ab?","ab,abc,abb,abcd,a,acd,abc")
['ab','ab','ab']

>>> re.findall("ab?",abcde")
['ab','ab']

匹配开头与结尾(^$): ^匹配指定字符开头的数据,$匹配指定字符结尾的数字.

>>> re.search(r"^h","hello world").group()
'h'
>>> re.search(r"world$","hello\nworld").group()
'world'
>>> re.search(r"^a","\nabc\ndef",flags=re.MULTILINE).group()
'a'
>>> re.search("foo$","bfoo\nsdfsf",flags=re.MULTILINE).group()
'foo'

匹配前一个字符出现次数(x{m}) 匹配前一个字符x,出现过m次的行.

>>> re.search("hello{2}","hello,helloo,hellooo,helloooo").group()
'helloo'

>>> re.search("hello{3}",helloooo").group()
'hellooo'

匹配前一个字符出现次数(x{n,m}) 匹配前一个字符x,最少出现过n次,最多出现过m次.

>>> re.search("hello{1,2}",helloooo").group()
'hello'

>>> re.findall("hello{1,helloooo")
['hello','helloo','helloo']

脱意字符的匹配(\) 转义字符,通常情况下使后一个字符改变原来的意思,也叫做脱意字符.

>>> re.search("..\\t","hello\t lyshark\n").group()
'lo\t'
>>> re.search("\\t","hello\t lyshark\n").group()
'\t'
>>> re.search("\t","hello\t lyshark\n").group()
'\t'
>>> re.search(r"\\","hello\\lyshark").group()
'\\'

匹配查找范围([]) 匹配查找指定的数据范围,通常使用[0-9] [a-z] [A-Z]这几个匹配格式.

>>> re.search("[0-9]","hello 1,2,3,4,5").group()   # 匹配第一次出现数字的行
'1'
>>> re.search("[0-9]","hello a12 b23 34a 45t").group()
'1'
>>> re.findall("[0-9]",5")          # 匹配所有出现数字的行
['1','2','3','4','5']
>>> re.findall("[0-9]","hello  b23 34a 45t wan")
['2','5']
>>> re.search("[^0-9]",5").group()  # 匹配开头不是0-9的单个字符
'h'
>>> re.search("[^0-9]*",5").group() # 匹配开头不是0-9的单行行
'hello'
>>> re.search(r"[aeiou]","Hello LyShark").group()
'e'

匹配查找空白字符(s) 匹配空白字符

>>> re.search("\s+","ab\tc1\n3").group()
'\t'
>>> re.search("\s+","ab c1\n3").group()
' '

选择性匹配(|) 匹配选择竖线左边,或者右边的任意一种情况.

>>> re.search("abc|ABC","ABCBabcCD").group()
'ABC'

>>> re.findall("abc|ABC","ABCBabcCD")
['ABC','abc']

实现分组匹配((?P...)) 匹配条件并自动分组,其中?P<..>是固定写法,后面紧跟正则规则.

>>> number = "371481199306143242"
>>> re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})",number).groupdict()
{'province': '3714','city': '81','birthday': '1993'}

>>> re.search("(?P<name>[a-zA-Z]+)(?P<age>[0-9]+)","lyshark22").groupdict("temp")
{'name': 'lyshark','age': '22'}

针对IP地址与MAC地址的提取:

>>> re.search("^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$","192.168.1.1")
<re.Match object; span=(0,11),match='192.168.1.1'>       # 匹配IP地址

>>> re.match(r"^\s*\d{1,3}\.\d{1,3}\s*$","192.168.1.100")
<re.Match object; span=(0,13),match='192.168.1.100'>     # 匹配IP地址

>>> string_ip = "is this 236.168.192.1 ip 12321"
>>> result = re.findall(r"\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b",string_ip)
>>> result
['236.168.192.1']

>>> string=re.compile(r'((1\d\d|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.){3}(1\d\d|2[0-4]\d|25[0-5]|[1-9]\d|\d)')
>>> print(string.search('245.255.256.25asdsa10.11.244.10').group())
10.11.244.10

>>> string_IPv6="1050:0:0:0:5:600:300c:326b"               # 匹配IPV6地址(大小写不敏感)
>>> re.match(r"^(?:[A-F0-9]{1,4}:){7}[A-F0-9]{1,4}$",string_IPv6,re.I)
<re.Match object; span=(0,26),match='1050:0:0:0:5:600:300c:326b'>

>>> re.findall(r"(?<![:.\w])(?:[A-F0-9]{1,4}(?![:.\w])",re.I)
['1050:0:0:0:5:600:300c:326b']

>>> re.match(r"^\s*([0-9a-fA-F]{2,2}:){5,5}[0-9a-fA-F]{2,2}\s*$","AB:1F:44:5B:3B:4A")
<re.Match object; span=(0,17),match='AB:1F:44:5B:3B:4A'> # 匹配一个MAC地址

针对网址与端口的匹配:

>>> re.search(r"^(http|https?:\/\/)([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$","https://www.baidu.com")
<re.Match object; span=(0,21),match='https://www.baidu.com'> # 匹配网址

>>> re.findall(r"([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-4]\d{4}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])","hello 443")
['4','3']                                            # 匹配端口号

>>> re.search(r'^(http|https?:\/\/)([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?(:([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-4]\d{4}|65[0-4]\d{2}|655[0-2]\d|6553[0-5]))?$',"http://www.baidu.com:80")
<re.Match object; span=(0,23),match='http://www.baidu.com:80'>

>>> re.search(r'^(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])(:([0-9]|[1-9]\d{1,"192.168.1.100:443")
<re.Match object; span=(0,match='192.168.1.100:443'>

针对时间格式的匹配:

>>> re.search(r"(\d{4}-\d{1,2}-\d{1,2})","2019-01-12")
<re.Match object; span=(0,10),match='2019-01-12'>

>>> re.findall(r"(\d{4}-\d{1,"2019-01-12,2010-12-11")
['2019-01-12','2010-12-11']

>>> re.findall(r"\d{4}[-/]\d{2}[-/]\d{2}",2010/12/11")
['2019-01-12','2010/12/11']

>>> re.search(r"(\d{1,2}/(Jan|Feb|Mar|Apr|Jun|Jul|Aug|Sep|Oct|Nov|Dec)/\d{4})",21/Nov/2019").group()
'21/Nov/2019'

>>> re.findall(r"(\d{1,2}:\d{1,"2010-12-11 12:11")
['12:11']

>>> re.findall(r"(\d{1,"2010-12-11 12:11:22,09:25:30")
['12:11:22','09:25:30']

>>> re.search(r"(\d{4}-\d{1,2}\s\d{1,"2010-12-11 12:11")
<re.Match object; span=(0,16),match='2010-12-11 12:11'>

>>> re.findall(r"(\d{4}-\d{1,"2010-12-11 12:11")
['2010-12-11 12:11']

匹配邮箱/手机号/身份证:

>>> re.search("^1[3|4|5|8]\d{9}$","18264856987")
<re.Match object; span=(0,match='18264856987'>       # 匹配手机号

>>> re.search("[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+","182648@qq.com")
<re.Match object; span=(0,match='182648@qq.com'>     # 匹配一个邮箱

>>> re.findall(r'(^[1-8][0-7]{2}\d{3}([12]\d{3})(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}([0-9X])$)',"33070219630306041X")
[('33070219630306041X','1963','03','06','X')]          # 匹配身份证号

针对密码验证的匹配: 此处的匹配正则常用于用户名密码的过滤.

>>> re.findall("[\u4e00-\u9fa5]","你好")
['你','好']       # 匹配中文字符

>>> re.findall("^[\u4e00-\u9fa5_a-zA-Z0-9]{4,10}$","1233")
['1233']           # 单纯限制字符的输入长度

>>> re.findall(r"^[a-zA-Z][a-zA-Z0-9_]{4,15}$","password")
['password']      # 允许输入最小5-15个字符的密码,允许使用下划线.

>>> re.findall(r"^[a-zA-Z]\w{5,17}$","passw3")
['passw3']        # 以字母开头,长度在6~18之间,只能包含字母、数字和下划线

>>> re.findall("^(?!_)(?!.*?_$)[a-zA-Z0-9_\u4e00-\u9fa5]+$","1233")
['1233']          # 限制不能以下划线开头和结尾

常用匹配函数

函数与方法名 通配符匹配作用解析
regex.match 从字符串开头位置匹配查找,如果0个或多个字符被匹配则返回相应的匹配对象,如果不匹配则返回None.
regex.search 扫描整个字符串,查找正则匹配到的字串中第一次出现的位置,并返回相应的匹配对象,如果匹配失败则返回None.
regex.findall 搜索字符串中与正则表达式匹配的所有子串,也就是查找字符串中所有的匹配结果,并且以列表的形式返回数据.
regex.sub 字符串的替换,简单来说就是替换字符串中与正则表达式匹配的指定数量的子串,最后返回替换修改后的字符串.
regex.split 以正则表达式匹配的字符串作为分隔符,对一个字符串进行分割,以列表形式返回分割后的各个字符串.
match.expand 通过得到的匹配对象来构造并返回一个新的字符串,未被匹配到的分组将被替换为一个空字符串.
match.group 返回一个或多个指定捕获组所匹配到的内容,如果只有1个参数则返回单独的字符串,多参数返回元组.
match.groups 返回一个包含所有分组所匹配内容的元组,如果某个分组没有匹配到内容,则取defalult所指定的值.
match.groupdict 返回一个包含所有命名分组名称及其所匹配内容的字典对象,如果某个分组没有匹配到内容则取默认值.

regex.match() 从起始位置开始匹配,匹配成功返回一个对象,未匹配成功返回None.

match(pattern,string,flags=0)
# pattern: 正则模型
# string : 要匹配的字符串
# falgs  : 匹配模式
#------------------------------------------------
#  未分组情况下.
>>> origin = "hello alex bcd abcd lge acd 19"
>>>
>>> ret = re.match("h\w+",origin)
>>> print(ret.group())                 #获取匹配到的所有结果
>>> print(ret.groups())                #获取模型中匹配到的分组结果
>>> print(ret.groupdict())             #获取模型中匹配到的分组结果

#  有分组情况下. 提取匹配成功的指定内容(先匹配成功全部正则,再匹配成功的局部内容提取出来)
>>> ret = re.match("h(\w+).*(?P<name>\d)$",origin)
>>> print(r.group())                   #获取匹配到的所有结果
>>> print(r.groups())                  #获取模型中匹配到的分组结果
>>> print(r.groupdict())               #获取模型中匹配到的分组中所有执行了key的组

regex.search() 搜索整个字符串去匹配第一个符合条件的数据,未匹配成功返回None.

>>> origin = "hello alex bcd abcd lge acd 19"
>>>
>>> re.search("^h\w+",origin).group()          #匹配开头是h的后面是任意字符的
'hello'
>>> re.search("a\w+",origin).group()           #匹配a开头后面是任意字符的
'alex'
>>> re.search("(?P<name>a\w+)",origin).groupdict()
{'name': 'alex'}                               #分组匹配并过滤出alex

>>> re.search("(?P<姓名>[a-zA-Z]+)(?P<年龄>[0-9]+)","lyshark22").groupdict()
{'姓名': 'lyshark','年龄': '22'}               #匹配字符串,并分组打印出结果

regex.findall() 获取非重复的匹配列表,且每一个匹配均是字符串,空的匹配也会包含在结果中.

>>> origin = "hello alex bcd abcd lge acd 19"

>>> re.findall("al\w+",origin)
['alex']                             #匹配到单个结果,则以单列表返回
>>> re.findall("a\w+",origin)
['alex','abcd','acd']              #匹配到多个结果,则以列表形式返回

regex.sub() 先匹配查找结果,然后进行字串的替换,也就是替换匹配成功的指定位置字符串.

sub(pattern,repl,count=0,flags=0)
# pattern: 正则模型
# repl   : 要替换的字符串或可执行对象
# string : 要匹配的字符串
# count  : 指定匹配个数
# flags  : 匹配模式

>>> origin = "hello alex bcd abcd lge acd 19"

>>> re.sub("a[a-z]+","999999",origin,1)      #匹配以a开头则字串,并替换成9999,替换1次
'hello 999999 bcd abcd lge acd 19'
>>> re.sub("a[a-z]+",2)      #匹配以a开头则字串,替换2次
'hello 999999 bcd 999999 lge acd 19'

regex.split() 字符串切割函数,用来实现对指定字符串的分割工作,根据正则匹配分割字符串.

split(pattern,maxsplit=0,flags=0)
# pattern: 正则模型
# string : 要匹配的字符串
# maxsplit:指定分割个数
# flags  : 匹配模式

>>> origin = "hello alex bcd abcd lge acd 19"

>>> re.split("alex",1)               #无分组切割
['hello ',' bcd abcd lge acd 19']
>>> re.split("(alex)",1)             #有分组,以alex最为分隔符,切割字符串
['hello ','alex',' bcd abcd lge acd 19']

单独匹配

>>> ptr = re.compile(r"[A-Z]")
>>> ptr.search("Hello lyshark")
<re.Match object; span=(0,1),match='H'>
>>> ptr.findall("Hello lyshark")
['H']

re.DOTALL

# 正则表达式默认以单行开始匹配的
import re

def re_pattern_syntax():
    # .表示任意单一字符
    # *表示前一个字符出现>=0次
    # re.DOTALL就可以匹配换行符\n,默认是以行来匹配的
    print(re.match(r'.*','abc\nedf').group())
    print('*' * 80)
    print(re.match(r'.*','abc\nedf',re.DOTALL).group())

if __name__ == '__main__':
    re_pattern_syntax()

re.MULTILINE

# 正则表达式默认以单行开始匹配的
import re

def re_pattern_syntax1():
    # ^表示字符串开头(单行)
    # re.MULTILINE多行匹配字符串开头
    print(re.findall(r'^abc','abc\nedf'))
    print('*' * 80)
    print(re.findall(r'^abc','abc\nabc',re.MULTILINE))

def re_pattern_syntax2():
    # $表示字符串结尾
    # re.MULTILINE表示行的结束
    print(re.findall(r'abc\d$','abc1\nabc2'))
    print('*' * 80)
    print(re.findall(r'abc\d$','abc1\nabc2',re.MULTILINE))

if __name__ == '__main__':
    re_pattern_syntax1()
    re_pattern_syntax2()

?非贪婪模式

import re

def re_pattern_syntax4():
    # greedy贪婪/non-greedy非贪婪,默认的是贪婪的匹配
    s = '<H1>title</H1>'
    print(re.match(r'<.+>',s).group())  #贪婪模式会匹配尽量多的匹配
    print(re.match(r'<.+?>',s).group()) #非贪婪模式匹配尽量少的匹配
    print(re.match(r'<(.+)>',s).group(1))
    print(re.match(r'<(.+?)>',s).group(1))

def re_pattern_syntax5():
    # {m}/{m,}/{m,n}
    print(re.match(r'ab{2,4}','abbbbbbb').group())  #贪婪模式尽量匹配多
    print(re.match(r'ab{2,4}?','abbbbbbb').group()) #非贪婪模式尽量匹配少
    print('*' * 80)

if __name__ == '__main__':
    re_pattern_syntax4()
    re_pattern_syntax5()

re.I/re.IGNORECASE

import re

def re_pattern_flags():
    # re.I/re.IGNORECASE
    print(re.match(r'(Name)\s*:\s*(\w+)','NAME : Joey',re.IGNORECASE).groups())
    print('*' * 80)

if __name__ == '__main__':
    re_pattern_syntax_meta_char()

re.VERBOSE

import re

def re_pattern_flags1():
    # re.VERBOSE此标识位可以添加注释/re.compile
    s = 'the number is 20.5'
    r = re.compile(r'''
                    \d+   # 整数部分
                    \.?   # 小数点,可能包含也可能不包含
                    \d*   # 小数部分,可选
                    ''',re.VERBOSE)
    print(re.search(r,s).group())
    print(r.search(s).group())
    print('*' * 80)

if __name__ == '__main__':
    re_pattern_syntax_meta_char1()

原文地址:https://www.cnblogs.com/LyShark

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Python中的函数(二) 在上一篇文章中提到了Python中函数的定义和使用,在这篇文章里我们来讨论下关于函数的一些更深的话题。在学习C语言函数的时候,遇到的问题主要有形参实参的区别、参数的传递和改变、变量的作用域。同样在Python中,关于对函数的理解和使用也存在这些问题。下面来逐一讲解。一.函
Python中的字符串 可能大多数人在学习C语言的时候,最先接触的数据类型就是字符串,因为大多教程都是以&quot;Hello world&quot;这个程序作为入门程序,这个程序中要打印的&quot;Hello world&quot;就是字符串。如果你做过自然语言处理方面的研究,并且用Python
Python 面向对象编程(一) 虽然Python是解释性语言,但是它是面向对象的,能够进行对象编程。下面就来了解一下如何在Python中进行对象编程。一.如何定义一个类 在进行python面向对象编程之前,先来了解几个术语:类,类对象,实例对象,属性,函数和方法。 类是对现实世界中一些事物的封装,
Python面向对象编程(二) 在前面一篇文章中谈到了类的基本定义和使用方法,这只体现了面向对象编程的三大特点之一:封装。下面就来了解一下另外两大特征:继承和多态。 在Python中,如果需要的话,可以让一个类去继承一个类,被继承的类称为父类或者超类、也可以称作基类,继承的类称为子类。并且Pytho
Python中的函数(一) 接触过C语言的朋友对函数这个词肯定非常熟悉,无论在哪门编程语言当中,函数(当然在某些语言里称作方法,意义是相同的)都扮演着至关重要的角色。今天就来了解一下Python中的函数用法。一.函数的定义 在某些编程语言当中,函数声明和函数定义是区分开的(在这些编程语言当中函数声明
在windows下如何快速搭建web.py开发框架 用Python进行web开发的话有很多框架供选择,比如最出名的Django,tornado等,除了这些框架之外,有一个轻量级的框架使用起来也是非常方便和顺手,就是web.py。它由一名黑客所创建,但是不幸的是这位创建者于2013年自杀了。据说现在由
将Sublime Text 2搭建成一个好用的IDE 说起编辑器,可能大部分人要推荐的是Vim和Emacs,本人用过Vim,功能确实强大,但是不是很习惯,之前一直有朋友推荐SUblime Text 2这款编辑器,然后这段时间就试了一下,就深深地喜欢上这款编辑器了...
Python中的模块 有过C语言编程经验的朋友都知道在C语言中如果要引用sqrt这个函数,必须用语句&quot;#include&lt;math.h&gt;&quot;引入math.h这个头文件,否则是无法正常进行调用的。那么在Python中,如果要引用一些内置的函数,该怎么处理呢?在Python中
Python的基础语法 在对Python有了基础的认识之后,下面来了解一下Python的基础语法,看看它和C语言、java之间的基础语法差异。一.变量、表达式和语句 Python中的语句也称作命令,比如print &quot;hello python&quot;这就是一条语句。 表达式,顾名思义,是
Eclipse+PyDevʽjango+Mysql搭建Python web开发环境 Python的web框架有很多,目前主流的有Django、Tornado、Web.py等,最流行的要属Django了,也是被大家最看好的框架之一。下面就来讲讲如何搭建Django的开发环境。一.准备工作 需要下载的
在windows下安装配置Ulipad 今天推荐一款轻便的文本编辑器Ulipad,用来写一些小的Python脚本非常方便。 Ulipad下载地址: https://github.com/limodou/ulipad http://files.cnblogs.com/dolphin0520/u...
Python中的函数(三) 在前面两篇文章中已经探讨了函数的一些相关用法,下面一起来了解一下函数参数类型的问题。在C语言中,调用函数时必须依照函数定义时的参数个数以及类型来传递参数,否则将会发生错误,这个是严格进行规定的。然而在Python中函数参数定义和传递的方式相比而言就灵活多了。一.函数参数的
在Notepad++中搭配Python开发环境 Python在最近几年一度成为最流行的语言之一,不仅仅是因为它简洁明了,更在于它的功能之强大。它不仅能够完成一般脚本语言所能做的事情,还能很方便快捷地进行大规模的项目开发。在学习Python之前我们来看一下Python的历史由来,&quot;Pytho
Python中的条件选择和循环语句 同C语言、Java一样,Python中也存在条件选择和循环语句,其风格和C语言、java的很类似,但是在写法和用法上还是有一些区别。今天就让我们一起来了解一下。一.条件选择语句 Python中条件选择语句的关键字为:if 、elif 、else这三个。其基本形式如
关于raw_input( )和sys.stdin.readline( )的区别 之前一直认为用raw_input( )和sys.stdin.readline( )来获取输入的效果完全相同,但是最近在写程序时有类似这样一段代码:import sysline = sys.stdin.readline()
初识Python 跟学习所有的编程语言一样,首先得了解这门语言的编程风格和最基础的语法。下面就让我们一起来了解一下Python的编程风格。1.逻辑行与物理行 在Python中有逻辑行和物理行这个概念,物理行是指在编辑器中实际看到的一行,逻辑行是指一条Python语句。在Python中提倡一个物理行只
当我们的代码是有访问网络相关的操作时,比如http请求或者访问远程数据库,经常可能会发生一些错误,有些错误可能重新去发送请求就会成功,本文分析常见可能需要重试的场景,并最后给出python代码实现。
1.经典迭代器 2.将Sentence中的__iter__改成生成器函数 改成生成器后用法不变,但更加简洁。 3.惰性实现 当列表比较大,占内存较大时,我们可以采用惰性实现,每次只读取一个元素到内存。 或者使用更简洁的生成器表达式 4.yield from itertools模块含有大量生成器函数可
本文介绍简单介绍socket的常用函数,并以python-kafka中的源码socketpair为例,来讲解python socket的运用
python实践中经常出现编码相关的异常,大多网上找资料而没有理解原理,导致一次次重复错误。本文对常用Unicode、UTF-8、GB2312编码的原理进行介绍,接着介绍了python字符类型unicode和str以及常见编解码错误UnicodeEncodeError和UnicodeDEcodeEr