python正则表达式

.  除'\n'外的任意一个字符,包含汉字(多行匹配方式下,也能匹配'\n')

*  量词,表示左边的字符可以出现0次或者任意多次

?  量词,表示左边的字符必须出现0次或者1次

+  量词,表示左边的字符必须出现1次或者更多次

{m}    量词,m是整数。表示左边的字符必须且只能出现m次

{m,n} 量词,m,n都是整数。表示左边的字符必须出现至少m次,最多n次。n也可以不写,表示出现的次数没有上限

 

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

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

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

\S  一个非空白字符

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

\W  一个不是单词字符的字符

|   A|B表示能匹配A或能匹配B均算匹配

 

正则表达式中的特殊字符:

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

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

正则表达式 匹配的字符串
'a\$b' 'a$b'
'a\*b' 'a*b'
'a\[\]b' 'a[]b'
'a\.*b'

'ab'

'a.b'

'a..b'

......(ab之间有0个或任意多个.)

'a\\\\b'

'a\\b'(注意:此字符串长度为3,中间那个字符是'\',

即r'a\b'。字符串前加r是为了防止转义)

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

范围符号:[]

用以表示“此处必须出现一个某某范围内的字符”,或者“此处必须出现一个字符,但不可以是某某范围内的字符”

[xxx]的用法,见下表

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

'sak'

's2k'

'sck'

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

'bak'

'bUk'

......

[\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'的字符    

匹配汉字:

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

 

量词的用法:

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

正则表达式示例:

[1-9]\d* 正整数
-[1-9]\d* 负整数
-?[1-9]\d*|0 整数
[1-9]\d*|0 非负整数
-?([1-9\d*\.\d*[1-9]|0\.\d*[0-9]|0]) 左右两边没有多余0的小数
\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)* 邮箱

正则表达式的函数

要实用正则表达式,首先需要导入re库

import re

1.     re.match()

Signature: re.match(pattern, string, flags=0)
Docstring:
Try to apply the pattern at the start of the string, returning
a match object, or None if no match was found.
File: /usr/lib64/python3.6/re.py
Type: function

flags标志位,用于控制模式串的匹配方式,如:是否区分大小写,多行匹配等等,如re.M | re.| 表示忽略大小写且多行匹配。

import re


def match(pattern, string):
    x = re.match(pattern, string)       # re.match() 从头开始匹配
    if x != None:
        print(x.group())
    else:
        print('None')


match("a c", "a cdkgh")
match("abc", "kabc")
match("a\tb*c", "a\tbbcde")
match("ab*c", "ac")
match("a\d+c", "ac")
match("a\d{2}c", "a34c")
match("a\d{2,}c", "a3474884c")
match(".{2}bc", "cbcd")
match(".{2}bc", "bcbcdbc")
match("ab.*", "ab")
match("ab.*", "abcd")
match("\d?b.*", "1bcd")
match("\d?b.*", "bbcd")
match("a?bc.*", "abbbcd")
match("a.b.*", "abcd")
match("a.b.*", "aeb")
match("a.?b.*", "aebcdf")
match("a.+b.*", "aegsfb")
match("a.+b.*", "abc")
match("a高.+k", "a高大kcd")

2.    re.search

Signature: re.search(pattern, string, flags=0)
Docstring:
Scan through string looking for a match to the pattern, returning
a match object, or None if no match was found.
File: /usr/lib64/python3.6/re.py
Type: function

re.search 只能找到第一个匹配的字符串

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("a.+bc*", "bcdbaegsfbccc")   # aegsfbccc (4, 13)
search("a.?bc*d", "dabccdc")        # abccd  (1, 6)
search("aa", "baaaa")       # aa (1, 3)
search("\([1-9]+\)", "ab123(0456)(789)45ab")  # (789) (11, 16)
search("[1-9]\d+", "ab01203d45")        # 1203 (3, 7)

3.   re.findall

Signature: re.findall(pattern, string, flags=0)
Docstring:
Return a list of all non-overlapping matches in the string.

If one or more capturing groups are present in the pattern, return
a list of groups; this will be a list of tuples if the pattern
has more than one group.

Empty matches are included in the result.
File: /usr/lib64/python3.6/re.py
Type: function

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

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."))   # []
print(re.findall('aaa', "baaaa"))           # ['aaa']

4.    re.finditer

Signature: re.finditer(pattern, string, flags=0)
Docstring:
Return an iterator over all non-overlapping matches in the
string. For each match, the iterator returns a match object.

Empty matches are included in the result.
File: /usr/lib64/python3.6/re.py
Type: function

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

5.    re.sub

Signature: re.sub(pattern, repl, string, count=0, flags=0)
Docstring:
Return the string obtained by replacing the leftmost
non-overlapping occurrences of the pattern in string by the
replacement repl. repl can be either a string or a callable;
if a string, backslash escapes in it are processed. If it is
a callable, it's passed the match object and must return
a replacement string to be used.
File: /usr/lib64/python3.6/re.py
Type: function

import re

str = re.sub('\d+', '...', 'abc13de4fg')
print(str)                  # abc...de...fg
print(re.sub('\d+', "", "abc13de4fg"))      # abcdefg
print(re.sub('gone', 'go', "I gone hegone me"))     # I go hego me

 边界符号

\A    表示字符串的左边界,即要求从此往左边不能有任何字符

\Z    表示字符串的右边界,即要求从此往右边不能有任何字符

^    与\A同。但多行匹配模式下还可以表示一行文字的左边界

$    与\Z同。但多行匹配模式下还可以表示一行文字的右边界

边界符号本身不会和任何字符匹配

\b    表示此处应为单词的左边界或者右边界,即不可是单词字符

\B    表示此处不允许是单词的左边界或者右边界,即必须是单词字符

正则表达式的边界符号'\b'是两个字符。但是在python字符中,'\b'和'\t','\n'类似,是一个字符(Backspace)。因此在正则表达式中使用边界符号\b,要写

'\\b'。如果写'\\\\b',则连续的两个'\'被看作一个普通的'\',不会和后面的'b'一起被当作字符组合,变成边界符号'\b'

 

import re

def search(pattern, string):
    x = re.search(pattern, string)
    if x != None:
        print(x.group(), x.span())
    else:
        print("None")


pt = 'ka\\b.*'          # 表示单词a的右边不能是字符
search(pt, "ka")        # ka (0, 2)
search(pt, "kax")       # None
search(pt, "ka?d")      # ka?d (0, 4)
pt = '.*\\bka\\b'
search(pt, "ka")        # ka (0, 2)
search(pt, "ska?")      # None
search(pt, "b?ka?")     # b?ka (0, 4)

m = r"\bA.*N\b T"
search(m, "Ass$NC TK")  # None
search(m, "this Ass$N TK")  # Ass$N T
m = "\BA.*N\B\w T"
search(m, "this Ass$N TK")  # None
search(m, "thisAss$NM TK")  # Ass$NM T
search(m, "Ass$NM TK")      # None
search(m, "xAss$NM TK")     # Ass$NM T
pt = '\\b高兴'
search(pt, "我高兴")           # None
search(pt, "我 高兴")          # 高兴

 分组

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

import re

x = re.search('[a-z]+(\d+)[a-z]+', "ab 123d hello553world47")
print(x.group(1))       # group(0)、group()返回整个匹配,group(1)返回第一个分组,groups返回从1开始匹配的分组
m = "(((ab*)c)d)e"
r = re.match(m, "abcdefg")
print(r.group(0))        # For 0 returns the entire match.  abcde
print(r.group(1))        # abcd
print(r.group(2))        # abc
print(r.group(3))        # ab
print(r.groups())        # Return a tuple containing all the subgroups of the match, from 1.
                         # ('abcd', 'abc', 'ab')


m = "(ab*)(c(d))e"
r = re.match(m, "abcdefg")
print(r.groups())       # ('ab', 'cd', 'd')
print(r.group(0))       # abcde
print(r.group(1))       # ab
print(r.group(2))       # cd
print(r.group(3))       # d

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

 

import re

m = r'(((ab*)c)d)e\3'
r = re.match(m, "abbbcdeabbbkfg")
print(r.group(3))           # abbb
print(r.group())            # abbbcdeabbb

pt = 'a(.)\\1*b'    # 等价于pt = r'a(.)\1*b'
print(re.search(pt, 'kacccccb').group()) # acccccb
print(re.search(pt, 'kaxxxxb').group()) # axxxxb
print(re.search(pt, 'kaxb').group()) # axb
x = re.search(pt, 'kaxyb')
if x != None:
print(x.group())

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

import re


m = "(((ab*)+c)d)e"
r = re.match(m, "ababcdefg")    # ('ababcd', 'ababc', 'ab')
print(r.groups())

r = re.match(m, "abacdefg")     # ('abacd', 'abac', 'a')  不要求分组的多次出现,必须匹配相同字符串
print(r.groups())

在正则表达式中没有分组时,re.findall返回所有匹配子串构成的列表。

有且只有一个分组时,re.findall返回的是一个子串的列表,每个元素是一个匹配子串中分组对应的内容

import re

m = '[a-z]+(\d+)[a-z]+'
x = re.findall(m, "13 bc12de ab11 cd320ef")
print(x)    #['12', '320']

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

2号分组、3号分组......匹配的内容

import re

m = '(\w+) (\w+)'
r = re.match(m, 'hello world')
print(r.groups())
print(r.group(1))
print(r.group(2))
r = re.findall(m, "hello world, this is very good")
print(r)

|的用法

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

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

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']

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

import re

m = "(((ab*)+c|12)d)e"
print(re.findall(m, 'ababcdefgKK12deKK'))  # [('ababcd', 'ababc', 'ab'), ('12d', '12', '')]
for x in re.finditer(m, 'ababcdefgKK12deKK'):
    print(x.groups())
# ('ababcd', 'ababc', 'ab')
# ('12d', '12', None)

m = '\[(\d+)\]|<(\d+)>'
for x in re.finditer(m, '233[32]88ab<443>'):
    print(x.group(), x.groups())
# [32] ('32', None)
# <443> (None, '443')

贪婪模式和懒惰模式

贪婪模式:量词+,*,?,{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']
print(re.findall('\(.+\)', "A dog has(have a).这(哈哈)true()me")) # ['(have a).这(哈哈)true()']

 懒惰模式:在量词+,*,?,{m,n}后面加'?'则匹配尽可能短的字符串

import re

m = "a.*?b"         # .*?表示.*采用懒惰匹配
for k in re.finditer(m, "aabab"):
    print(k.group(), end=" ")               # aab ab
m = "<h3>.*?</h3>"
a = re.match(m, "<h3>abd</h3><h3>bcd</h3>")
print(a.group())               # <h3>abd</h3>
m = "<h3>.*?[M|K]</h3>"
a = re.match(m, "<h3>abd</h3><h3>bcK</h3>") # <h3>abd</h3><h3>bcK</h3>
print(a.group())
print(re.findall('\d+?', "this is 334 what me 774gw"))
# [3, 3, 4, 7, 7, 4]
print(re.findall('[a-zA-Z]+?', "A dog has 4 legs.这是true"))
# ['A', 'd', 'o', 'g', 'h', 'a', 's', 'l', 'e', 'g', 's', 't', 'r', 'u', 'e']
print(re.findall('\(.*?\)', "A dog has(have).这(哈哈)true()me"))
# ['(have)', '(哈哈)', '()']

 匹配对象的函数

string:匹配时使用的母串

lastindex:最后一个被匹配的分组的编号(不是最大编号)。如果没有被匹配的分组,将为None

group([n1,n2,...]):

  • 获得一个或多个分组匹配的字符串;指定多个参数时将以元组形式返回。n1,n2,...可以使用编号也可以使用名字
  • 编号0代表整个匹配的子串(与模式里的"()"无关)
  • group()等价于group(0)
  • 没有匹配字符串的组返回None
  • 匹配了多次的组返回最后一次匹配的子串

groups([default]):

以元组形式返回全部分组匹配的字符串。相当于调用group(1,2,...last)。

defalut表示没有匹配字符串的组以这个值替代,默认为None。

start([group]):

返回指定的组匹配的子串在string中的起始位置。group默认值为0

end([group]):

返回指定的组匹配的子串在string中的结束位置(子串最后一个字符的位置+1)。group默认值为0

span([group]):

返回(start(group), end(group))

group可以是组编号,也可以是组名字,缺省为0

import re

m = re.match(r'(\w+) (\w+)(.)', 'hello world!ss')
print(m.string)         # 匹配的字符串是'hello world!ss'
print(m.lastindex)      # 3
print(m.group(0, 1, 2, 3))  # ('hello world!', 'hello', 'world', '!')
print(m.groups())       # ('hello', 'world', '!')
print(m.start(2))       # 6
print(m.end(2))         # 11
print(m.span(2))        # (6, 11)

 

posted @ 2021-04-18 22:12  李成敏  阅读(181)  评论(0编辑  收藏  举报