007-re 正则

re 正则

正则匹配 re 模块:https://docs.python.org/zh-cn/3/library/re.html

一、扩展表示法

1、(?aiLmsux)

( ‘a’, ‘i’, ‘L’, ‘m’, ‘s’, ‘u’, ‘x’ 中的一个或多个) 这个组合匹配一个空字符串;这些字符对正则表达式设置以下标记 re.Are.A (只匹配ASCII字符), re.I (忽略大小写), re.L (语言依赖), re.M (多行模式), re.S (点dot匹配全部字符), re.U (Unicode匹配), and re.X (冗长模式)。 (这些标记在 模块内容 中描述) 如果你想将这些标记包含在正则表达式中,这个方法就很有用,免去了在 re.compile() 中传递 flag 参数。标记应该在表达式字符串首位表示。

'''
1、(?iLmsux):
	i:忽略大小
	L:
	m:Multiline - 多行模式
	s:Singleline - 单行模式
	u:表示和问号的作用差不多,用于设置"贪婪模式"。
	x:忽略正则表达式中的空白字符,除非它已经被转义。
'''
a = re.findall(r'\d+one\.\w+', '31one.com')
b = re.findall(r'\d+one\.\w+', '31One.com')
c = re.findall(r'\d+one\.\w+', '31One.com', flags=re.I)
d = re.findall(r'(?i)\d+one\.\w+', '31One.com')
print(a)    # ['31one.com']
print(b)    # []
print(c)    # ['31One.com']
print(d)    # ['31One.com']

c = re.findall('(?i)to','welcom to china,Tom,t中,国家,t-m,t_m,123,')
print(c)    # ['to', 'To']

c = re.findall('(?ix)t o','welcom to china,Tom,t中,国家,t-m,t_m,123,t o')
print(c)    # ['to', 'To']

c = re.findall('(?ix)t\ o','welcom to china,Tom,t中,国家,t-m,t_m,123,t o')
print(c)    # ['t o']

c = re.findall('(?iu)t','welcom to china,Tom,t中,国tt家,t-m,t_m,123,t o')
print(c)    # ['t', 'T', 't', 't', 't', 't', 't', 't']

2、(?:…)

正则括号的非捕获版本(不存储匹配结果)。 匹配在括号内的任何正则表达式,但该分组所匹配的子字符串 不能 在执行匹配后被获取或是之后在模式中被引用。

a = re.search(r'\w+', 'tom3year.com')
b = re.search(r'(?:\w+)', 'tom3year.com')
c = re.search(r'(\w+)?(?(1)\.\w+|\w+)', 'tom3year.com')
print(a.group())    # tom3year
print(b.group())    # tom3year
print(c.group())    # tom3year.com

re.search(r'(?:\w+)?(?(1)\.\w+|\w+)', 'tom3year.com')   # 报错
'''
因为 (?:\w+) 匹配的结果没有存储,所以后面的匹配模式 ?(1) 不能取到分组查询的结果,所以报错;
而 c = re.search(r'(\w+)?(?(1)\.\w+|\w+)', 'tom3year.com') 中,(\w+) 匹配的结果被存储了,所以后面的匹配模式 ?(1) 能取到分组查询的结果
'''

3、(?aiLmsux-imsx:…)

(‘a’, ‘i’, ‘L’, ‘m’, ‘s’, ‘u’, ‘x’ 中的0或者多个, 之后可选跟随 ‘-’ 在后面跟随 ‘i’ , ‘m’ , ‘s’ , ‘x’ 中的一到多个 .) 这些字符为表达式的其中一部分 设置 或者 去除 相应标记 re.A (只匹配ASCII), re.I (忽略大小写), re.L (语言依赖), re.M (多行), re.S (点匹配所有字符), re.U (Unicode匹配), and re.X (冗长模式)。(标记描述在 模块内容 .)
 
‘a’, ‘L’ and ‘u’ 作为内联标记是相互排斥的, 所以它们不能结合在一起,或者跟随 ‘-’ 。 当他们中的某个出现在内联组中,它就覆盖了括号组内的匹配模式。在Unicode样式中, (?a:…) 切换为 只匹配ASCII, (?u:…) 切换为Unicode匹配 (默认). 在byte样式中 (?L:…) 切换为语言依赖模式, (?a:…) 切换为 只匹配ASCII (默认)。这种方式只覆盖组合内匹配,括号外的匹配模式不受影响。

略 … … … … … …

4、(?P…)

给正则分组匹配标识为 name。
(命名组合)类似正则组合,但是匹配到的子串组在外部是通过定义的 name 来获取的。组合名必须是有效的 Python 标识符,并且每个组合名只能用一个正则表达式定义,只能定义一次。一个符号组合同样是一个数字组合,就像这个组合没有被命名一样。

命名组合可以在三种上下文中引用。如果样式是 (?P<quote>['"]).*?(?P=quote) (也就是说,匹配单引号或者双引号括起来的字符串):
在这里插入图片描述

str_ = f"""
hi "tom", I'm cat,
"""
a = re.search(r'(?P<quote>[\'\"]).*?(?P=quote)', str_)  
print(a.group())    # "tom"
a = re.findall(r'(?P<quote>[\'\"]).*?(?P=quote)', str_)
print(a)            # ['"']

5、(?P=name)

反向引用一个命名组合;它匹配前面那个叫 name 的命名组中匹配到的串同样的字串。

6、(?#…)

注释;里面的内容会被忽略。

7、(?=…)

匹配 … 之前的内容,但是并不消费样式的内容。这个叫做 前视断言(lookahead assertion)。比如, Isaac (?=Asimov) 匹配 'Isaac ’ 只有在后面是 ‘Asimov’ 的时候。
获取 (?=…) 之前的正则匹配的内容。

# 获取 tom 之前的字符串

str_ = 'now77tom.com cat77nice.com'
a = re.findall(r'\w+(?=tom)',str_)
print(a)    # ['now77']

str_ = str_ = 'now77tom.com cat77tom.com'
a = re.findall(r'\w+(?=tom)',str_)
print(a)    # ['now77', 'cat77']

str_ = str_ = 'now77tom com cat77tom com'
a = re.findall(r'\w+(?=tom).*?',str_)
print(a)    # ['now77', 'cat77']

8、(?!…)

匹配 … 不符合的情况。这个叫 negative lookahead assertion (前视取反)。比如说, Isaac (?!Asimov) 只有后面 不是 ‘Asimov’ 的时候才匹配 'Isaac ’ 。

str_ = 'now77 tom com stom nice'
a = re.findall(r'\w+ (?!tom).*?',str_)
print(a)    # ['tom ', 'com ', 'stom ']

9、(?<=…)

匹配前面是 … 的且符合后面正则的字符串。

匹配字符串的当前位置,它的前面匹配 … 的内容到当前位置。这叫:dfn:positive lookbehind assertion (正向后视断定)。 (?<=abc)def 会在 ‘abcdef’ 中找到一个匹配,因为后视会往后看3个字符并检查是否包含匹配的样式。包含的匹配样式必须是定长的,意思就是 abc 或 a|b 是允许的,但是 a* 和 a{3,4} 不可以。注意以 positive lookbehind assertions 开始的样式,如 (?<=abc)def ,并不是从 a 开始搜索,而是从 d 往回看的。你可能更加愿意使用 search() 函数,而不是 match() 函数:

# 匹配前面是abc的单词字符
str_ = 'tomabcnice whoareyou abcgood'
a = re.findall(r'(?<=abc)\w+', str_)
print(a)    # ['nice', 'good']

10、(?<!…)

匹配前面不是 … 的且符合后面正则的字符串。

匹配当前位置之前不是 … 的样式。这个叫 negative lookbehind assertion (后视断定取非)。类似正向后视断定,包含的样式匹配必须是定长的。由 negative lookbehind assertion 开始的样式可以从字符串搜索开始的位置进行匹配。

str_ = 'tomabcnice whoareyou abcgood'
a = re.findall(r'(?<!abc)\w+', str_)
print(a)    # ['tomabcnice', 'whoareyou', 'abcgood']

11、(?(id/name)yes-pattern|no-pattern)

如果给定的 id 或 name 存在,将会尝试匹配 yes-pattern ,否则就尝试匹配 no-pattern,no-pattern 可选,也可以被忽略。
id是有无命名分组的分组序号。
name是有命名分组的分组名称。

?(id/name) 指定的分组如果匹配到了非空数据,则使用 yes-pattern 进行匹配;否则使用 no-pattern 进行匹配。

x = re.search(r'(\d+)(?(1)\w+|pythontab\.\w+)', 'pythontab.com')
y = re.search(r'(\d+)?(?(1)\w+|pythontab\.\w+)', 'pythontab.com')
z = re.search(r'(\d+)(?(1)\w+|pythontab\.\w+)', '1pythontab.com')
k = re.search(r'(\d+)?(?(1)\w+|pythontab\.\w+)', '1pythontab.com')
h = re.search(r'(\d+)?(?(1)\w+|pythontab\.\w+)', 'pythontab.com')
print(x)            # None
print(y.group())    # pythontab.com
print(z.group())    # 1pythontab
print(k.group())    # 1pythontab
print(h.group())    # pythontab.com

12、其他

'''
\number:

\A:只匹配字符串开始。

\b:匹配一个单词边界,匹配空字符串,但只在单词开始或结尾的位置。

\B:匹配空字符串,但 不 能在词的开头或者结尾。

\d:
	对于 Unicode (str) 样式:
		匹配任何Unicode十进制数(就是在Unicode字符目录[Nd]里的字符)。这包括了 [0-9] ,和很多其他的数字字符。如果设置了 ASCII 标志,就只匹配 [0-9] 。
	对于8位(bytes)样式:
		匹配任何十进制数,就是 [0-9]。

\D:匹配任何非十进制数字的字符。就是 \d 取非。 如果设置了 ASCII 标志,就相当于 [^0-9] 。

\s:
	对于 Unicode (str) 样式:
		匹配任何Unicode空白字符(包括 [ \t\n\r\f\v] ,还有很多其他字符,比如不同语言排版规则约定的不换行空格)。如果 ASCII 被设置,就只匹配 [ \t\n\r\f\v] 。
	对于8位(bytes)样式:
		匹配ASCII中的空白字符,就是 [ \t\n\r\f\v] 。

\S:匹配任何非空白字符。就是 \s 取非。如果设置了 ASCII 标志,就相当于 [^ \t\n\r\f\v] 。

\w:
	对于 Unicode (str) 样式:
		匹配Unicode词语的字符,包含了可以构成词语的绝大部分字符,也包括数字和下划线。如果设置了 ASCII 标志,就只匹配 [a-zA-Z0-9_] 。
	对于8位(bytes)样式:
		匹配ASCII字符中的数字和字母和下划线,就是 [a-zA-Z0-9_] 。如果设置了 LOCALE 标记,就匹配当前语言区域的数字和字母和下划线。

\W:匹配非单词字符的字符。这与 \w 正相反。如果使用了 ASCII 旗标,这就等价于 [^a-zA-Z0-9_]。如果使用了 LOCALE 旗标,则会匹配当前区域中既非字母数字也非下划线的字符。

\Z:只匹配字符串尾。
'''
str_ = 'abc nice,ok'
a = re.findall(r'\b', str_)
print(a)    # ['', '', '', '', '', '']

# \b:匹配一个单词的边界;\B:匹配一个单词的中间(即不是边界)
pattern = re.compile(r'er\b')
c = pattern.findall('erc')
print(c)    # []
c = pattern.findall('never')
print(c)    # ['er']
c = pattern.findall('very')
print(c)    # []

pattern = re.compile(r'er\B')
c = pattern.findall('erc')
print(c)    # ['er']
c = pattern.findall('never')
print(c)    # []
c = pattern.findall('very')
print(c)    # ['er']

注意:

  • ‘\u’, ‘\U’ 和 ‘\N’ 转义序列只在 Unicode 模式中可被识别。 在 bytes 模式中它们会导致错误。 未知的 ASCII 字母转义序列保留在未来使用,会被当作错误来处理。
  • 八进制转义包含为一个有限形式。如果首位数字是 0, 或者有三个八进制数位,那么就认为它是八进制转义。其他的情况,就看作是组引用。对于字符串文本,八进制转义最多有三个数位长。

二、模块内容

1、re.compile(pattern, flags=0)

将正则表达式的样式编译为一个 正则表达式对象 (正则对象),可以用于匹配,通过这个对象的方法 match(), search() 以及其他如下描述。

prog = re.compile(pattern)
result = prog.match(string)

# 等价于

result = re.match(pattern, string)

如果需要多次使用这个正则表达式的话,使用 re.compile() 和保存这个正则对象以便复用,可以让程序更加高效。

注解
通过 re.compile() 编译后的样式,和模块级的函数会被缓存, 所以少数的正则表达式使用无需考虑编译的问题。

2、match(pattern,str[,flags])

匹配字符串开始位置,没有匹配到则返回 None,匹配成功则返回匹配的对象。

通过 group() 取出匹配的字符串,通过 span() 来取出匹配的位置,start() 取匹配到的开始位置,end() 取匹配到的结束位置。

一般用来判断是否是以什么开头的。

c = re.match('to','welcom to china')
print(c)    # None

c = re.match('to','tos china s')
print(c)            # <_sre.SRE_Match object; span=(0, 2), match='to'>
print(c.string)     # tos china s
print(c.group())    # to

c = re.match('\d+','123tos china 321s')
print(c.group())    # 123
print(c.span())     # (0,3)
print(c.start())    # 0
print(c.end())      # 3

c = re.match('\d+.*','123tos china 321s')
print(c.group())    # 123tos china 321s

c = re.match('(\d+).*','123tos china 321s')
print(c.group())    # 123tos china 321s
print(c.group(1))   # 123

line = "Cats are smarter than dogs"
matchObj = re.match(r'(.*) are (.*?) .*', line, re.M | re.I)
print(matchObj)             # <_sre.SRE_Match object; span=(0, 26), match='Cats are smarter than dogs'>
print(matchObj.group())     # Cats are smarter than dogs
print(matchObj.group(1))    # Cats
print(matchObj.group(2))    # smarter

3、search(pattern, str[, flags])

匹配字符串,返回第一个匹配成功的对象,不成功则返回 None。

line = "Cats are smarter than dogs";
searchObj = re.search(r'(.*) are (.*?) .*', line, re.M | re.I)
print(searchObj.group())    # Cats are smarter than dogs
print(searchObj.group(1))   # Cats
print(searchObj.group(2))   # smarter

4、sub(pattern, repl, string, count=0, flags=0)

检索并替换。

参数:
pattern : 正则中的模式字符串。
repl : 替换的字符串,也可为一个函数。
string : 要被查找替换的原始字符串。
count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。

phone = "2004-959-559 |# 这是一个国外电话号码"
# 删除字符串中的 Python注释
num = re.sub(r'#.*$', "", phone)
print("电话号码是: ", num)       # 电话号码是:  2004-959-559 |
# 删除非数字(-)的字符串
num = re.sub(r'\D', "", phone)
print("电话号码是 : ", num)      # 电话号码是 :  2004959559

5、compile(pattern[, flags])

用于编译正则表达式,生成一个正则表达式( Pattern )对象。

参数:
pattern : 一个字符串形式的正则表达式
flags : 可选,表示匹配模式,比如忽略大小写,多行模式等,具体参数为:

  • re.I 忽略大小写
  • re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境
  • re.M 多行模式
  • re.S 即为 . 并且包括换行符在内的任意字符(. 不包括换行符)
  • re.U 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库
  • re.X 为了增加可读性,忽略空格和 # 后面的注释

6、findall(string[, pos[, endpos]])

匹配所有符合条件的子串,并返回一个列表,如果没有找到匹配的,则返回空列表。

参数:
string : 待匹配的字符串。
pos : 可选参数,指定字符串的起始位置,默认为 0。
endpos : 可选参数,指定字符串的结束位置,默认为字符串的长度。

pattern = re.compile(r'\d+')  # 查找数字
result1 = pattern.findall('runoob 123 google 456')
result2 = pattern.findall('run88oob123google456', 0, 10)
print(result1)  # ['123', '456']
print(result2)  # ['88', '12']

7、finditer(pattern, string, flags=0)

在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。

it = re.finditer(r"\d+","12a32bc43jf")
for match in it:
	print (match.group() )
# 输出
12
32
43

8、split(pattern, string[, maxsplit=0, flags=0])

split 方法按照能够匹配的子串将字符串分割后返回列表

参数:
pattern:匹配的正则表达式
string:要匹配的字符串。
maxsplit:分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数。
flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:正则表达式修饰符 - 可选标志

c = re.split('\W+', 'runoob, runoob, runoob.')
print(c)    # ['runoob', 'runoob', 'runoob', '']

c = re.split('(\W+)', ' runoob, runoob, runoob.')
print(c)    # ['', ' ', 'runoob', ', ', 'runoob', ', ', 'runoob', '.', '']

c = re.split('\W+', ' runoob, runoob, runoob.', 1)
print(c)    # ['', 'runoob, runoob, runoob.']

c = re.split('a*', 'hello world')   # 对于一个找不到匹配的字符串而言,split 不会对其作出分割
print(c)    # ['hello world']

9、其他

略…

三、匹配对象

https://docs.python.org/zh-cn/3/library/re.html#re.Match.group

匹配对象总是有一个布尔值 True。如果没有匹配的话 match() 和 search() 返回 None。

匹配对象支持以下方法和属性:

匹配对象方法都将组 0 作为默认参数。

  • Match.expand(template)
    对 template 进行反斜杠转义替换并且返回,就像 sub() 方法中一样。转义如同 \n 被转换成合适的字符,数字引用(\1, \2)和命名组合(\g<1>, \g) 替换为相应组合的内容。
     
    在 3.5 版更改: 不匹配的组合替换为空字符串。

1、Match.group([group1, …])

返回一个或者多个匹配的子组(返回整个正则匹配的结果和子组结果)。

整个正则匹配的结果记为组 0,其他子组编号从 1 开始。
组从 0 开始编号。组 0 始终存在;它表示整个正则。子组从 1 开始。

1)如果只有一个参数,结果就是一个字符串(0 为整个正则匹配结果,其他为子组匹配结果);
2)如果有多个参数,结果就是一个元组(每个参数对应一个子组);
3)如果没有参数,返回整个正则匹配结果(组 0)。 

如果一个组 N 参数值为 0,相应的返回值就是整个匹配字符串;如果它是一个范围 [1…99],结果就是相应的括号组字符串。如果一个组号是负数,或者大于样式中定义的组数,一个 IndexError 索引错误就 raise。如果一个组包含在样式的一部分,并被匹配多次,就返回最后一个匹配。

import re

m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")
print(m)    # <re.Match object; span=(0, 12), match='Isaac Newton'>

n = m.groups()
print(n)    # ('Isaac', 'Newton')

a = m.group()
print(a)    # Isaac Newton

b = m.group(0)
print(b)    # Isaac Newton

c = m.group(1)
print(c)    # Isaac

d = m.group(2)
print(d)    # Newton

e = m.group(1, 2)
print(e)    # ('Isaac', 'Newton')

f = m.group(0, 2)
print(f)    # ('Isaac Newton', 'Newton')

如果正则表达式使用了 (?P…) 语法, groupN 参数就也可能是命名组合的名字。如果一个字符串参数在样式中未定义为组合名,一个 IndexError 就 raise。
命名组合同样也可以通过索引值引用:

import os
import re

m = re.match(r"(?P<one>\w+) (?P<two>\w+)", "Isaac Newton, physicist")
print(m)    # <re.Match object; span=(0, 12), match='Isaac Newton'>

n = m.groups()
print(n)    # ('Isaac', 'Newton')

a = m.group()
print(a)    # Isaac Newton

b = m.group(0)
print(b)    # Isaac Newton

c = m.group(1)
print(c)    # Isaac
c2 = m.group('one')
print(c2)    # Isaac

d = m.group(2)
print(d)    # Newton
d2 = m.group('two')
print(d2)    # Isaac

e = m.group(1, 2)
print(e)    # ('Isaac', 'Newton')
e2 = m.group('one', 'two')
print(e2)    # ('Isaac', 'Newton')

f = m.group(0, 2)
print(f)    # ('Isaac Newton', 'Newton')
f2 = m.group(0, 'two')
print(f2)    # ('Isaac Newton', 'Newton')

如果一个组匹配成功多次,就只返回最后一个匹配:

import re

m = re.match(r"(..)+", "a1b2c3")  # Matches 3 times.
a = m.groups()      # ('c3',)
b = m.group()       # a1b2c3
c = m.group(0)      # a1b2c3
d = m.group(1)      # c3

获取分组结果更方便的方式(3.6 新版功能):

import re

m = re.match(r"(?P<one>\w+) (?P<two>\w+)", "Isaac Newton, physicist")
print(m)    # <re.Match object; span=(0, 12), match='Isaac Newton'>
print(m[0]) # Isaac Newton
print(m[1]) # Isaac
print(m[2]) # Newton

2、Match.groups(default=None)

返回一个元组,包含所有匹配的子组,在样式中出现的从1到任意多的组合。 default 参数用于为未匹配到的分组设置默认值,默认为 None。

import re

m = re.match(r"(\d+)\.(\d+)", "24.1632")
m.groups()	# ('24', '1632')

m = re.match(r"(\d+)(\d+)?", "24.123")
m.groups()  # ('24', None)

m = re.match(r"(\d+)(\d+)?", "24.123")
m.groups('空')  # ('24', '空')

3、Match.groupdict(default=None)

返回一个字典,包含了所有的 命名 子组。key就是组名。 default 参数用于不参与匹配的组合;默认为 None。

import re

m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds")
m.groupdict()	# {'first_name': 'Malcolm', 'last_name': 'Reynolds'}

m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)?", "Malcolm --tom")
a = m.groupdict('空')    # {'first_name': 'Malcolm', 'last_name': '空'}
print(a)

4、Match.start([group])

5、Match.end([group])

返回 group 匹配到的字串的开始和结束标号。group 默认为0(意思是整个匹配的子串)。如果 group 存在,但未产生匹配,就返回 -1 。对于一个匹配对象 m, 和一个未参与匹配的组 g ,组 g (等价于 m.group(g))产生的匹配是

6、Match.span([group])

对于一个匹配 m , 返回一个二元组 (m.start(group), m.end(group)) 。 注意如果 group 没有在这个匹配中,就返回 (-1, -1) 。group 默认为0,就是整个匹配。

7、Match.pos

pos 的值,会传递给 search() 或 match() 的方法 a 正则对象 。这个是正则引擎开始在字符串搜索一个匹配的索引位置。

8、Match.endpos

endpos 的值,会传递给 search() 或 match() 的方法 a 正则对象 。这个是正则引擎停止在字符串搜索一个匹配的索引位置。

9、Match.lastindex

捕获组的最后一个匹配的整数索引值,或者 None 如果没有匹配产生的话。比如,对于字符串 ‘ab’,表达式 (a)b, ((a)(b)), 和 ((ab)) 将得到 lastindex == 1 , 而 (a)(b) 会得到 lastindex == 2 。

10、Match.lastgroup

最后一个匹配的命名组名字,或者 None 如果没有产生匹配的话。

11、Match.re

返回产生这个实例的 正则对象 , 这个实例是由 正则对象的 match() 或 search() 方法产生的。

12、Match.string

传递到 match() 或 search() 的字符串。

四、search() VS match()

  • re.match():检查字符串开头,匹配以指定模式开头的字符串。
  • re.search():检查字符串的任意位置,匹配包含指定模式的字符串。
re.match("c", "abcdef")    # No match
re.search("c", "abcdef")   # Match 
<re.Match object; span=(2, 3), match='c'>

1)在 search() 中,可以用 ^ 作为开始来限制匹配到字符串的首位。

re.match("c", "abcdef")    # No match
re.search("^c", "abcdef")  # No match
re.search("^a", "abcdef")  # Match
<re.Match object; span=(0, 1), match='a'>

2)注意 MULTILINE 多行模式中函数 match() 只匹配字符串的开始,但在 search() 中使用以 ^ 开始的正则表达式会匹配每行的开始。

re.match('X', 'A\nB\nX', re.MULTILINE)  # No match
re.search('^X', 'A\nB\nX', re.MULTILINE)  # Match
<re.Match object; span=(4, 5), match='X'>

五、单词匹配 \w

\w:匹配单词字符,包括 大小字母、数字、下划线,等价于 [A-Za-z0-9_]
因环境和应用情景不同,在某些情景下还可以匹配汉字。如:

在 python 中,\w 可以匹配大小写字母、数字、下划线和汉字。
如果开启了 re.A(re.ASCII) 标志,就只匹配 [a-zA-Z0-9_]。

在 js 中,\w 只能匹配大小写字母、数字、下划线。(可能随着版本的更新,也会随着变化)

六、正则匹配出不同的值,并分别替换成不同的值

import re

str_ = """10000

OK

请求正常

请求正常

10001

INVALID_USER_KEY

key不正确或过期

开发者发起请求时,传入的key不正确或者过期 

10002

SERVICE_NOT_AVAILABLE

没有权限使用相应的服务或者请求接口的路径拼写错误

1.开发者没有权限使用相应的服务,例如:开发者申请了WEB定位功能的key,却使用该key访问逆地理编码功能时,就会返回该错误。反之亦然。

10003

DAILY_QUERY_OVER_LIMIT

访问已超出日访问量

开发者的日访问量超限,被系统自动封停,第二天0:00会自动解封。

10004

ACCESS_TOO_FREQUENT

单位时间内访问过于频繁

开发者的单位时间内(1分钟)访问量超限,被系统自动封停,下一分钟自动解封。
    """

str_ = f"{{ {str_} }}"
# print(str_)
pat = re.compile(r'(?P<infocode>\d{5}|\d{3}\*\*)\s+(?P<infoword>[A-Z_]{2,})\s+(?P<errmsg>.*?)\s+(?P<detail>.*)(\s{1})')

# 全部替换
res = pat.sub(r'"\g<infocode>":{"code":"\g<infoword>","err_msg":"\g<errmsg>","detail":"\g<detail>"},',str_)
print(res)

输出结果:

{ "10000":{"code":"OK","err_msg":"请求正常","detail":"请求正常"},
"10001":{"code":"INVALID_USER_KEY","err_msg":"key不正确或过期","detail":"开发者发起请求时,传入的key不正确或者过期 "},
"10002":{"code":"SERVICE_NOT_AVAILABLE","err_msg":"没有权限使用相应的服务或者请求接口的路径拼写错误","detail":"1.开发者没有权限使用相应的服务,例如:开发者申请了WEB定位功能的key,却使用该key访问逆地理编码功能时,就会返回该错误。反之亦然。"},
"10003":{"code":"DAILY_QUERY_OVER_LIMIT","err_msg":"访问已超出日访问量","detail":"开发者的日访问量超限,被系统自动封停,第二天0:00会自动解封。"},
"10004":{"code":"ACCESS_TOO_FREQUENT","err_msg":"单位时间内访问过于频繁","detail":"开发者的单位时间内(1分钟)访问量超限,被系统自动封停,下一分钟自动解封。"},     }
# 只替换一次
res = pat.sub(r'"\g<infocode>":{"code":"\g<infoword>","err_msg":"\g<errmsg>","detail":"\g<detail>"},',str_,count=1)
print(res)

输出结果:

{ "10000":{"code":"OK","err_msg":"请求正常","detail":"请求正常"},
10001

INVALID_USER_KEY

key不正确或过期

开发者发起请求时,传入的key不正确或者过期 

10002

SERVICE_NOT_AVAILABLE

没有权限使用相应的服务或者请求接口的路径拼写错误

1.开发者没有权限使用相应的服务,例如:开发者申请了WEB定位功能的key,却使用该key访问逆地理编码功能时,就会返回该错误。反之亦然。

10003

DAILY_QUERY_OVER_LIMIT

访问已超出日访问量

开发者的日访问量超限,被系统自动封停,第二天0:00会自动解封。

10004

ACCESS_TOO_FREQUENT

单位时间内访问过于频繁

开发者的单位时间内(1分钟)访问量超限,被系统自动封停,下一分钟自动解封。
     }

七、另

1、范围匹配
	[''-a]:ASCII 码中,所有字符都位于 "" 和 a 之间,即 34~97 之间

2、闭包操作符:*	+
	*:Kleene 闭包,匹配 0 次或多次
	+:正闭包,匹配 1 次或多次
	注意:
		?:表示匹配 0 次或 1 次
		? 跟在闭包操作符后,表示在匹配成功的前提下,尽可能少的匹配

3、html 标签匹配
	</?[^>]+>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值