Python:正则表达式 详解!!

目录

一、正式表达式

1.概念和组成

2.字符范围和量词

2.1 [xxx]的用法

2.2 匹配汉字

2.3量词的用法

二、正则表达式的函数

1.re.match函数

2.re.search函数

re.match与re.search的区别

3.re.findall函数

4.re.finditer函数

5.re.sub 替换匹配的子串

三、边界符号

四、分组(...)

re.findall和分组

五、| 的用法(或)

 六、贪婪模式和懒惰模式

七、“匹配对象”的函数


一、正式表达式

1.概念和组成

正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配

字符/组合匹配的模式正则表达式匹配的字符串
.代表任何一个字符,除了换行符(\n),包括汉字(多行匹配方式下也能匹配\n)'a.b'

'acb'

'adb'

'a(b'

……

*量词。表示它左边的字符可以出现0~n'a*b'

'b'

'ab'

'aaaab'

……

?(英文问号)量词。表示它左边的字符必须出现0次或1次'ka?b'

'kb'

'kab'

+量词。表示它左边的字符必须出现1次或n次'ka+b'

'kab'

'kaaaab'

{m}量词。m是整数。表示它左边的字符必须且只能出现m次'ka{3}b''kaaab'
{m,n}量词。m,n是整数。表示它左边的字符必须出现至少m次最多n次。n也可以不写,表示出现次数没有上限(如{3,})'ka{1,3}b'

'kab'

'kaab'

'kaaab'

\d一个数字字符,等价于[0-9]'a\db'

'a2b'

'a1b'

……

\D

一个非数字字符,等价于[^\d],[^0-9]

(^表示非)

'a\Db'

'acb'

……

\s一个空白字符,如空格,\t,\r,\n等'a\sb'

'a b'

'a\nb'

……

\S一个非空白字符'a\Sb'

'akb'

……

\w一个单词字符:包括汉字或大小写英文字母,数字,下划线,或者其他语言的文字'a\wb'

'a_b'

'a中b'

……

\W一个不是单词字符的字符'a\Wb''a?b'
|A|B表示能匹配A能匹配B均算能匹配'ab|c'

'ab'

'c'

^(字符串)行的开始    ^first  表示行以first开头
$(字符串)行的结尾     last$  表示行以last结尾

print("\\s\S\w\W\d\D")
#Python字符串中,\s等不是转义字符,都是两个字符
#>>\s\S\w\W\d\D

正则表达式中常见的特殊字符有以下几个:

. + ? $ [] () ^ {} \

如果要在正则表达式中表示这几个字符本身,就应该在其前面加“\”

正则表达式 -- 匹配的字符

'a\$b'   -- 'a$b'

'a\\\\b'  -- 'a\\b' (注意:在Python中“\\”表示一个“\”,所以此字符串长度为3,中间那个字符是'\',即 r'a\b')

r'a\\b'   -- r'a\b' (r'a\b'等价于 'a\\b' )

特殊字符使用反斜杠引导,例如”\r"、"\n"、"\t"、"\"分别表示回车、换行、制表符号与反斜线自己本身.
 

2.字符范围和量词

2.1 [xxx]的用法

[] 内的元字符不起作用,只表示普通字符。

^放在[]中表示排除的意思(非)

[a2c]匹配'a','2','c'之一's[a2c]k'

'sak'

's2k'

'sck'

[a-z A-Z]匹配任一英文字母'b[a-z A-Z]k'

'bak'

bWk'

……

[\da-z\?]匹配一个数字或小写英文字母或'?''b[\da-z\?]k'

'b0k'

'bck'

'b?k'

[^abc]匹配一个非'a' , 'b' , 'c' 之一的字符'b[^abc]k'

匹配所有能匹配'b.k'的字符串,除了:

'bak'   'bbk'  'bck'

[^a-f0-3]匹配一个非英文字母'a'到'f',也非数字'0'到'3'的字符

2.2 匹配汉字

汉字的unicode编码范围是 4e00-9fa5(16进制),因此[\u4e00-\u9fa5] 即表示一个汉字。

(16进制前要加“\u”)

如:\u4e00  :表示“一”

2.3量词的用法

'.+'匹配任意长度不为0且不含'\n'的字符串。'+'表示左边的'.'代表的任意字符出现1次或n次。不要求出现的字符都一样。
'.*'匹配任意不含'\n'的字符串,包括空串
'[\dac]+'匹配长度不为0的由数字或'a','c'构成的串,如'451a' , 'a21c78ca'
'\w{5}'

匹配长度为5的由字母或数字或汉字构成的串,如'高达abc' ,

'22我a1'

例:

[1-9]\d*   :正整数([1-9]表示数字1-9任意一个,“\d”表示数字等价于[0-9],“*”表示它左边的字符可以出现0~n次)(即[1-9]打头,后面跟0~n个数字)

-[1-9]\d*   :负整数

-?[1-9]\d*|0  : 整数(|表示或,“?”表示它左边的字符必须出现0次或1次

[1-9]\d*|0   :非负整数

-?([1-9]\d*\.\d*[1-9] | 0\.\d*[1-9] | 0) :左右都没有多余的0的小数(“\.”即“.”)(例:2.4  0.8 0)

二、正则表达式的函数

re 模块使 Python 语言拥有全部的正则表达式功能。

1.re.match函数

语法:re.match(pattern, string, flags=0)
  • 从字符串的起始位置匹配一个模式pattern,若起始位置匹配成功则返回一个匹配对象,否则返回 none
  • pattern匹配的正则表达式
    string要匹配的字符串。
    flags

    标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。如:

    re.M | re.I  表示忽略大小写,且多行匹配  I是 i 的大写字母

import re
def match(pattern,string):
    x = re.match(pattern,string)
    if x != None:
        print(x.group())       #x.group是匹配上的字符串
    else:
        print("None")
match("a c","a cdkgh")         #>>a c
match("abc","kabc")            #>>None   虽然有abc,但不是在起始位置
match("a\tb*c","a\tbbccde")    #>>a bbc   “\t”表示制表符(这里为空格),b出现0次或任意多次,然后跟c
match("a.?b.*","aebcdf")        #>>aebcdf

2.re.search函数

语法:re.search(pattern, string, flags=0)
  • 查找字符串中可以匹配成功的子串
  • 若匹配成功,则返回第一个成功的匹配对象,否则返回None。
import re
print(re.search('www', 'www.runoob.com').span())         # 在起始位置匹配,输出子串起止位置
print(re.search('com', 'www.runoob.com').span())         # 不在起始位置匹配

#>>(0, 3)
#>>(11, 14)    (后面字符串中的索引,从0开始)

import re
def search(pattern,string):
    x = re.search(pattern,string)
    if x != None:
        print(x.group(),x.span())              #输出子串及起止位置
    else:
        print("None")
search("a.+bc*","dbaegsfbcef")                #>>aegsfbc (2, 9)
search("\([1-9]+\)","ab123(0456)(789)45ab")   #>>(789) (11,16)    “\(”表示“(”  ; “\)”表示“)”

re.match与re.search的区别

re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。

3.re.findall函数

语法:re.findall(pattern, string, flags=0)

  • 查找字符串中所有和模式匹配的子串(不重叠)放入列表。一个子串都找不到就返回空表[ ]

注:返回的是列表

import re
print(re.findall('\d+',"this is 334 what me 774gw"))         #>>['334', '774']
print(re.findall('[a-zA-Z]+',"A dog has 4 legs.这是true"))    #>>['A', 'dog', 'has', 'legs', 'true']
print(re.findall('\d+',"this is good."))                     #>>[]
import re
pattern = r'mr_\w+'
print(pattern)           # >>mr_\w+   r+字符串表示字符串里面的转义字符木有用
string = 'MR_SHOP mr_shop'
match = re.findall(pattern,string,re.I)     # re.I 表示不区分英文字母大小写
print(match)            # >>['MR_SHOP', 'mr_shop']

4.re.finditer函数

语法:re.finditer(pattern, string, flags=0)
  • 查找字符串中所有和模式匹配的子串(不重叠),每个子串对应于一个匹配对象,返回匹配对象的序列(准确说是“可调用迭代器”)
import re
s = '233[32]88ab<433>(21)'
m = '\[\d+\]|<\d+>'     #|表示或 ,<>表示尖括号
for x in re.finditer(m,s):
    print(x.group(),x.span())
i = 0
for y in re.finditer(m,"aaaaa"):
    i += 1           #不会被执行

#>>[32] (3, 7)
#>><433> (11, 16)

5.re.sub 替换匹配的子串

语法:re.sub(模式串,替换串,母串)     用于替换匹配的子串

import re
str = re.sub('\d+',"...","abc13de4fg")            #将在母串中与模式串匹配的子串用替换串代替
print(str)                                        #>>abc...de...fg
print(re.sub('\d+',"","abc13de4fg"))              #>>abcdefg
print(re.sub('eating',"sleeping","I love eating!"))       #>>I love sleeping!

6. re.split()分割字符串

语法:re.split(pattern, string, [maxsplit][flags=0])

maxsplit  -- 可选参数,表示最大的拆分次数

import re
pat = r'[?|&]'    #注意pattern是字符串哦,要加引号
url = 'http://www.mingrisoft.com/login.jps?username="mr"&pwd="mrsoft"'
result = re.split(pat,url)
print(result)   #>>['http://www.mingrisoft.com/login.jps', 'username="mr"', 'pwd="mrsoft"']

三、边界符号

\A表示字符串的边界,即要求从此往左边不能有任何字符
\Z表示字符串的边界,即要求从此往右边不能有任何字符
^与\A同。但多行匹配模式下还可以表示一行文字的左边界
$与\Z同。但多行匹配模式下还可以表示一行文字的右边界
\b表示此处应为单词的左边界或右边界,即不可是单词字符
\B表示此处不允许是单词的左边界或右边界,即必须是单词字符

  • 边界符号本身不会和任何字符匹配
  • Python中字符串'\A' , '\Z','\B' 都是两个字符,而不是像'\n'那样的一个字符
  • 正则表达式的边界符号'\b'两个字符。但是在Python字符串中,是一个字符因此在正则表达式中使用边界符号\b,要写'\\b'。如果写成'\\\\b',则连续的两个'\'被看作是一个普通的'\',不会和后面的'b'一起被当作字符组合,变成边界符号'\b'

print("\A\Z")     #>>\A\Z

pt = "ka\\b.*"          #表示ka的左边不能是单词字符(单词字符即)
search(pt,"ka")         #>>ka
search(pt,"kax")        #>>None  因为ka的左边x是单词字符
search(pt,"ka?d")       #>>ka?d  ?不是单词字符,d满足“.”

pt = ".*\\bka\\b"       #表示ka的左边、右边都不能是单词字符
search(pt,"ka")         #>>ka
search(pt,"ska?")       #>>None
search(pt,"b?ka?")      #>>b?ka

m = r"\bA.*N\b T"       #等价于m = "\\bA.*N\b T"

四、分组(...)

括号中的表达式是一个分组。多个分组按左括号从左到右从1开始依次编号

import re
x = re.search('[a-z]+(\d+)[a-z]+',"ab 123d hello553world47")   #表示:一个或多个小写字母 一个或多个数字 一个或多个小写字母 即hello553world满足
print(x.group(1))            #>>553
print(x.group())             #>>hello553world
m = "(((ab*)c)d)e"           #即表示多个分组,要按左括号从左到右从1开始分组 (((ab*)c)d)e即1号分组,((ab*)c)d即2号分组,……
r = re.match(m,"abcdefg")
print(r.group())             #>>abcde
print(r.group(0))            #>>abcde    group(0)等价于group()
print(r.group(1))            #>>abcd
print(r.group(2))            #>>abc
print(r.group(3))            #>>ab
print(r.groups())            #>>('abcd', 'abc', 'ab')

使用 group(num) 或 groups() 匹配对象函数来获取匹配表达式。

匹配对象方法描述
group(num=0)匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
groups()返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。

在分组的右边可以通过分组的编号引用该分组所匹配的子串

import re
m = r'(((ab*)c)d)e\3'       #r表示字符串里的'\'不再转义  等价于m = '(((ab*)c)d)e\\3'
#要求 ab*cde后面跟着3号分组在本次匹配中匹配上的子串
r = re.match(m,"abbcdeabbbkfg")    #最后3个b(bbb)少一个b则不能匹配
print(r.group(3))             #>>abb
print(r.group())              #>>abbcdeabb

分组作为一个整体,后面可以跟量词

import re
m = "(((ab*)+c)d)e"
r = re.match(m,"ababcdefg")
print(r.groups())                #>>('ababcd', 'ababc', 'ab')  即分别表示1号分组,2号分组,3号分组
r = re.match(m,"abacdefg")
print(r.groups())               #>>('abacd', 'abac', 'a')  
#不要求分组的多次出现必须匹配相同的字符串

re.findall和分组

在正则表达式中没有分组时,re.findall返回所有匹配子串构成的列表有且只有一个分组时,re.findall返回的是一个子串的列表,每个元素是一个匹配子串中分组对应的内容

import re
m = '[a-z]+(\d+)[a-z]+'
x = re.findall(m,"13 bc12de ab11 cd320ef")  #满足条件的m:bc12de cd320ef
print(x)             #>>['12', '320']

在正则表达式中有超过一个分组时,re.findall返回的是一个元组的列表每个元组对应于一个匹配的子串,元组里的元素,依次是1号分组、2号分组、3号分组……匹配的内容

import re
m = '(\w+) (\w+)'
r = re.match(m,"hello world")
print(r.groups())       #>>('hello', 'world')
print(r.group(1))       #>>hello
print(r.group(2))       #>>world
r = re.findall(m,"hello world,this is very good")
#找出由所有能匹配的子串的groups()构成的元组,互相不重叠
print(r)                #>>[('hello', 'world'), ('this', 'is'), ('very', 'good')]

五、| 的用法(或)

表示“或”,如果没有放在“()”中,则起作用的范围是直到整个正则表达式开头或结尾或另一个“|”

"\w{4}ce|c\d{3}|p\w"

从左到右短路匹配(匹配上一个后就不计算是否还能匹配后面的)

#从左到右短路匹配(匹配上一个后就不计算是否还能匹配后面的)
import re
pt = "\d+\.\d+|\d+"
print(re.findall(pt,"12.34 this is 125"))   #>>['12.34', '125']
pt = "aa|aab"
print(re.findall(pt,"aabcdeaa12aab"))       #>>['aa', 'aa', 'aa']  因为aa已经匹配上了,所以aab一直匹配不了

'|' 也可以用于分组中,起作用的范围仅限于分组内

import re
m = "(((ab*)+c|12)d)e"
print(re.findall(m,'ababcdefgkk12dek'))
#>>[('ababcd','ababc','ab'),('12d','12','')]

 六、贪婪模式和懒惰模式

量词+,*,?,{m,n}默认匹配尽可能的子串

import re
print(re.match("ab*","abbbbk").group())    #>>abbbb
print(re.findall("<h3>(.*)</h3>","<h3>abd</h3><h3>bcd</h3>"))   #>>['abd</h3><h3>bcd']

在量词 +,*,?,{m,n}后面加“?”则匹配尽可能的字符串

import re
m = "a.*?b"
for k in re.finditer(m,"aabab"):
    print(k.group(),end=" ")     #>>aab ab

七、“匹配对象”的函数

  • 使用 group(num) 或 groups() 匹配对象函数来获取匹配表达式。
匹配对象方法描述
group(num=0)匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。group() <==> group(0)
groups()

返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。

  • groupdict()  :
  • start([group]) 方法用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0;
  • end([group]) 方法用于获取分组匹配的子串在整个字符串中的结束位置子串最后一个字符的索引+1),(终点位置不算)参数默认值为 0;
  • span([group]) 方法返回 (start(group), end(group))
import re
m = re.match(r'(\w+) (\w+)(.)','hello world!ss')   #第1个分组“(\w+)”匹配“hello",第2个分组“(\w+)”匹配“world”,第3个分组“(.)”匹配“!“
print(m.string)            #>>hello world!ss   string表示母串
print(m.lastindex)         #>>3     lastindex表示在整个母串中最后一个被匹配的分组编号,从左到右从1开始
print(m.group(0,1,2,3))    #>>('hello world!', 'hello', 'world', '!')
print(m.group())           #>>hello world!
print(m.groups())          #>>('hello', 'world', '!')   相当于group(1,2,3)
print(m.start())           #>>0
print(m.start(2))          #>>6   第2个分组的起始位置”w“的索引   索引从0开始数
print(m.end())             #>>12
print(m.end(2))            #>>11   子串最后一个字符的索引+1),(终点位置不算)
print(m.span())            #>>(0,12)
print(m.span(2))           #>>(6,11)

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值