python进阶(十七)正则&json(上)
阅读原文时间:2023年07月09日阅读:3

1. 一个列表中所有的数字都是重复2次,但是有一个数字只重复了一次。

请找出重复一次的数字,不可以使用内置函数。

[2,2,1,1,0,4,3,4,3]

方法1:通过字典计数,找到value等于1的key

s = [2,2,1,1,0,4,3,4,3]

m = {}

for i in s:

if i in m:

m[i]+=1

else:

m[i] = 1

print(m)

for k,v in m.items():

if v ==1:

print (k)

#运行结果:

#{2: 2, 1: 2, 0: 1, 4: 2, 3: 2}

#0

方法2:使用排序,判断在头、中、尾三种情况

s = [2,2,1,1,0,4,3,4,3]

s = sorted(s)

for i in range(len(s)):

if i == 0 and s[1] !=s[0]:

print(s[0])

break

elif i == lens(s)-1 and s[i] s=s[i-1]:

print(s[i])

else:

if i!=len(s)-1 and i!=0 and s[i]!=s[i+1] and s[i]!=s[i-1]:

print(s[i])

break

#运行结果:

#0

方法3:使用内置函数append和remove

s = [2,2,1,1,0,4,3,4,3,0,-1]

relist = []

for i in s:

if i in relist:

relist.remove(i)

else:

relist.append(i)

print(relist[0])

#运行结果:

#-1

方法4:使用字典,优点:哈希查找,速度快

s = [2,2,1,1,0,4,3,4,3,0,-1]

redict = {}

for i in s:

try:

redict[i] +=1

del redict[i]

except:

redict[i] = 1

print(redict.keys())

#运行结果:

#dict_keys([-1])

print(list(redict.keys()))

#运行结果:

#[-1]

print(list(redict.keys())[0])

#运行结果:

#-1

输出结果时,换个方法:

print(redict)            #查看redict中的内容

#{-1: 1}

print(dir(redict))        #查看字典可用的方法

#['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']

print(redict.popitem()) #使用pop.item方法,将字典转换为tuple,且在源字典中删除该组

#(-1, 1)

print(redict)         #再次查看redict,已经变成空,因为redict中只有一个key和value

{}

print(redict.popitem()[0])#所以,要将所有代码写在一起,防止pop后在取值取不到报错

-1

d = {1:2,3:4}         #有两组key和value的字典

print(d.popitem())

#(3, 4)              #popitem出来的是第二组的key和value

print(d)

#{1: 2}              #再次查看原字典,只留下未pop的数据

print(d.popitem())

#(1, 2)

2. 写个程序可以处理下面的情况

Example 1:

Input: s = "leetcode", wordDict = ["leet", "code"]

Output: true

Explanation: Return true because "leetcode" can be segmented as "leet code".

Example 2:

Input: s = "applepenapple", wordDict = ["apple", "pen"]

0utput: true

Explanation: Return true because " applepenapple" can be segmented as "apple pen apple".

Note that you are allowed to reuse a dictionary word.

Example 3:

Input: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]

Output: false

方法1:

import re

s = "leetcode"

word_dict = ["leet","code"]

pattern = re.compile("("+"|".join(word_dict)+")")

print(pattern)

#re.compile('(leet|code)')

result = pattern.findall(s)

print(result)

#['leet', 'code']

print(len("".join(result))==len(s))

#True

import re

s = "leetcodex"

word_dict = ["leet","code"]

pattern = re.compile("("+"|".join(word_dict)+")")

print(pattern)

#re.compile('(leet|code)')

result = pattern.findall(s)

print(result)

#['leet', 'code']

print(len("".join(result))==len(s))

#False

方法2:

import re

s = "leetcode"

word_dict = ["leet","code"]

result = s

for i in word_dict:

result = "".join(re.split(i,result))

print(result == "")

#True

import re

s = "leetcodex"

word_dict = ["leet","code"]

result = s

for i in word_dict:

result = "".join(re.split(i,result))

print(result == "")

#False

一、正则表达式

1、正则表达式 – 后向引用

正则表达式中,放在圆括号”()”中的表示是一个分组。然后我们就可以对整个组使用一些正则操作,例如重复操作符。

要注意的是,只有”()”才能形成分组,””用于定义字符串,而“{}”用于定义重复操作。当用”()”定义了一个正则表达式分组后,正则引擎就会把匹配的组按照顺序进行编号,然后存入缓存中。这样我们就可以在后面对已经匹配过的内容进行引用,这就叫后向引用。

1. 通过索引引用

\数字

\1表示引用第一个分组,\2引用第二个分组,以此类推,而\0则表示引用整个被匹配的正则表达式本身。

2. 通过命名分组名进行引用(如果有的话)

(?P=name)

字符P必须是大写的P,name表示命名分组的分组名。

注意:

这些引用都必须是在正则表达式中才有效,用于匹配一些重复的字符串。

1) 通过默认分组编号进行后向引用

import re

s = "22 22 aa"

print(re.search(r"(\d{2}) \1",s).group())  #\1的意思是必须匹配和第一个分组匹配一样的内容

#22 22                            #后向引用,引用了分组1

s = "22 aa 22"

print(re.search(r"(\d{2}) \1",s).group())

#AttributeError: 'NoneType' object has no attribute 'group'

s = "22 21 22"

print(re.search(r"(\d{2}) \1",s).group()) #虽然21满足\d{2},但是21和22的内容不一样,即

\1匹配到的内容和\d{2}匹配到的内容不一样,所以未匹配成功

#AttributeError: 'NoneType' object has no attribute 'group'

\1表示第一个分组匹配到的内容

2) 通过命名分组进行后向引用

import re

res = re.search(r'(?Pgo)\s+(?P=name)\s+(?P=name)', 'go go go')

print(res.group())

#go go go

3) 交换字符串的位置

import re

s = "abc.xyz"

res = re.sub(r"(.*)\.(.*)",r"\2.\1",s)

print(res)

#xyz.abc

2、正则表达式 – 前向肯定断言与后向肯定断言

前向肯定断言的语法:

(?<=pattern)

前向肯定断言表示你希望匹配的字符串前面是pattern匹配的内容时,才匹配

后向肯定断言的语法是:

(?=pattern)

后向肯定断言表示你希望匹配的字符串是后面是pattern匹配的内容时,才匹配

import re

print(re.search(r"(?<=abc)\d+","abc123").group())#匹配前面是abc的多个数字

#123

print(re.search(r"(?<=abc)\d+","a1c123").group())

#AttributeError: 'NoneType' object has no attribute 'group'

print(re.search(r"\d+(?=abc)","123abc").group()) #匹配后面是abc的多个数字

#123

print(re.search(r"\d+(?=abc)","123a1c").group())

#AttributeError: 'NoneType' object has no attribute 'group'

前向肯定断言括号中的正则表达式必须是能确定长度的正则表达式,比如\W{3},而不能写成\w*或者\w+或者\w?等这种不能确定个数的正则模式符。

import re

s = "aaa111aaa,bbb222,333ccc"

print(re.findall(r"(?<=[a-z]{3})\d+(?=[a-z]+)",s))   #指定前后肯定断言

#['111']

print(re.findall(r"(?<=[a-z]{3})\d+",s))          #指定前向肯定断言

#['111', '222']

print(re.findall(r"\d+(?=[a-z]+)",s))             #指定后向肯定断言

#['111', '333']

print(re.findall(r"[a-z]+\d+[a-z]+",s))           #普通匹配方法

#['aaa111aaa']

try:

matchResult = re.findall(r"(?<=[a-]+)\d+(?=[a-z+])",s)#前向肯定未固定宽度

except Exception as e:

print(e)

else:

print(matchResult)

#look-behind requires fixed-width pattern  #前向匹配需要固定宽度的匹配模式

3、正则表达式 – 前向否定断言与后向否定断言

前向否定断言的语法:

(?<!pattern)

前向否定断言表示你希望匹配的字符串的前面不是pattern匹配的内容时,才匹配。

后向否定断言的语法:

后向否定断言表示你希望匹配的字符串的后面不是pattern匹配的内容时,才匹配。

和前向肯定断言一样,前向否定断言括号中的正则表达式必须是能确定长度的正则表达式,比如\W{3},而不能写成\w*或者\w+或者\w?等这种不能确定个数的正则模式符。

import re

s = "aaa111aaa,bbb222,333ccc"

print(re.findall(r"(?<![a-z]{3})\d+(?![a-z]+)",s))  #指定前后否定断言

#['1', '22', '33']

print(re.findall(r"(?<![a-z]{3})\d+",s))         #指定前向否定断言

#[['11', '22', '333']

print(re.findall(r"\d+(?![a-z]+)",s))           #指定后向否定断言

#['11', '222', '33']

print(re.findall(r"[a-z]+\d+[a-z]+",s))         #普通匹配方法

#['aaa111aaa']

try:

matchResult = re.findall(r"(?\d+(?![a-z+])",s)#前向否定断言未确定长度

except Exception as e:

print(e)

else:

print(matchResult)

#look-behind requires fixed-width pattern

===============================================================

二、JSON

1、使用Python语言来编码和解码JSON对象

Python的json模块序列化和反序列化分别是dumps和loads

json.dumps():将一个Python对象编码成JSON字符串

json.loads():将JSON格式字符串解码成Python对象

对简单的数据类型可以直接处理。如:string,Unicode,int,float,list,tuple,dict

2、JSON简介

JSON:JavaScript Object Notation(JavaScript对象表示法)

JSON:是存储和交换文本信息的语法。类似XML(存储数据的格式,有格式的存储数据)

JSON比XML更小、更快,更易解析。

3、JSON语法与语法规则

1) JSON语法:

JSON语法是JavaScript语法的子集。

2) JSON语法规则:

JSON语法是JavaScript对象表示法语法的子集。

1. 数据在名称/值对中

2. 数据由逗号分隔

3. 花括号保存对象

4. 方括号保存数组

4、JSON名称/值对

Json数据的书写格式是

名称/值对

名称/值对包括字段名称,后面写一个冒号,然后是值,比如:

“firstName”:”John”

等价于下面这条JavaScript语句:

firstName = “John”

JSON值可以是:

数字(整数或浮点数)

字符串(在双引号中)

逻辑值(true 或false),区别于Python的True和False

数组(在方括号中)

对象(在花括号中)

null

5、JSON对象

JSON对象是在花括号中书写的。对象可以包含多个名称/值对。比如:

{“firstName”:”John”,”lastName”:”Doe”}

这等价于JavaScript语句:

firstName = “John”

lastName = “Doe”

6、JSON数组

JSON数组是在方括号中书写的。数组可以包含多个对象。比如:

a = {

"employees":[

{"firstName":"John","lastName":"Doe"},

{"firstName":"Anna","lastName":"Smith"},

{"firstName":"Peter","lastName":"Jones"}

]

}

print(a)

在上面的例子中,对象”employees”是包含三个对象的数组。每个对象代表一条关于某人(有姓和名)的记录。

7、JSON解码:

1)将json格式字符串解码成Python对象,我们使用的是json.loads()函数,可以将

简单数据类型解码成Python对象。

json.loads                           #将json串转换为dict类型

>>> s = '{"name":"hehe","age":"18"}'      #s定义了一个json串

>>> print(s)

{"name":"hehe","age":"18"}

>>> print(type(s))                         #json串的数据类型是str

>>> import json                           #引入json包

>>> json.loads(s)                         #json.loads(s)将json串转换为dict类型

{'name': 'hehe', 'age': '18'}

>>> print(type(json.loads(s)))              #查看json.loads后的数据类型,是dict

>>> s                                   #查看经过json.loads后的s是否有变化

'{"name":"liuyujing","age":"18"}'             #s没有变化

>>> s1 = json.loads(s)

>>> print(type(s1))

>>> print(s) #s是str类型,但是print(s)是没有””的

{"name":"liuyujing","age":"18"}

>>> print(type(s))

>>> s #交互模式下,直接s会显示’’

'{"name":"liuyujing","age":"18"}'

>>> data = [{'a':"Aasdf",'b':(2,4),'c':3.0}]    #原始数据中有tuple(2,4)

>>> json.dumps(data)

'[{"a": "Aasdf", "b": [2, 4], "c": 3.0}]'        #经过json编码后,变成了JSON的数组

>>> json.loads(json.dumps(data))       #经过json解码后,原tuple类型转化成list类型

[{'a': 'Aasdf', 'b': [2, 4], 'c': 3.0}]

#编码过程中,Python中的listtuple都被转化成json的数组,而解码后,json的数组最终转化为Pythonlist,无论原来是list还是tuple

2)从jsonPython的类型转化

JSON字符串类型

Python类型

object

dict

array

list

string

unicode

number(int)

int

uumber(real)

float

true

True

false

False

null

None

>>> a = [{1:12, 'a':12.3}, [1,2,3], (1,2), 'asd', 'ad', 12, 13, 3.3,True,False,None]

>>> json.dumps(a)

'[{"1": 12, "a": 12.3}, [1, 2, 3], [1, 2], "asd", "ad", 12, 13, 3.3, true, false, null]'

>>> json.loads(json.dumps(a))

[{'1': 12, 'a': 12.3}, [1, 2, 3], [1, 2], 'asd', 'ad', 12, 13, 3.3, True, False, None]

注意:

json格式的字符串解码成Python对象以后,String类型都变成了Unicode类型,数组变成了list,不会回到原来的元祖类型,字典key的字符类型也被转成Unicode类型。

8、JSON编码

1). 使用json.dumps()方法来将一个Python数据类型列表编码成json格式的字符串。

json.dumps()                      #将dict类型,转换为json串

>>> print(json.dumps(s1))               #在上面已说明,s1是字典类型

{"name": "liuyujing", "age": "18"}

>>> type(s1)

>>> s2 = json.dumps(s1)                #json.dumps()将字典类型转换为json串

>>> print(s2)

{"name": "liuyujing", "age": "18"}

>>> print(type(s2))

>>> s2

'{"name": "liuyujing", "age": "18"}'

2)从Python到JSON字符串类型转化

>>> import json

>>> data = [{'a':"A",'b':(2,4),'c':3.0}]

>>> res = repr(data)             #有什么用?

>>> print("data :", res)

data : [{'a': 'A', 'b': (2, 4), 'c': 3.0}]

>>> data_json = json.dumps(data)

>>> print(data_json)

[{"a": "A", "b": [2, 4], "c": 3.0}]

#观察两次打印的结果,会发现Python对象被转成JSON字符串以后,跟原始的repr()输出的结果会有些特殊的变化,原字典中的元祖被改成了json类型的数组。

在json编码的过程中,会存在从Python原始类型转化json类型的过程,但这两种语言的类型存在一些差异,对照表如下:

Python类型

JSON字符串类型

dict

object

list,tuple

array

str,Unicode

string

int,long,float

number

True

true

False

flase

None

null

json.dumps支持将以上Python类型转换为JSON字符串类型

>>> json.dumps({1:2})             #会自动将dict的key值加上””

'{"1": 2}'

>>> json.loads(json.dumps({1:2}))   #loads后,原dict中的key值的””依然存在

{'1': 2}

>>> json.dumps([1,2])             #将list转换为数组(array)

'[1, 2]'

>>> json.dumps((1,2))             #将tuple转化为数组(array)

'[1, 2]'

>>> json.dumps(["hehe"])

'["hehe"]'

>>> json.dumps(["1",2,{1:2},("asx")])

'["1", 2, {"1": 2}, "asx"]'         #依次将list中的每个元素转换为对应的JSON字符串类型

>>> json.dumps(["1",2,{1:2},("asx","jing")])

'["1", 2, {"1": 2}, ["asx", "jing"]]'

>>> type(("asx"))

>>> json.dumps(True)

'true'

>>> json.loads(json.dumps(True))

True

>>> json.dumps(False)

'false'

>>> json.loads(json.dumps(False))

False

>>> json.dumps(None)

'null'

>>> json.loads(json.dumps(None))#无返回值

>>>

>>> print(json.loads(json.dumps(None)))
None

3) Json.dumps()

函数原型

9、eval                               #将json串转换为dict

>>> s                                  #s是个json串

'{"name":"liuyujing","age":"18"}'

>>> eval(s)                             #eval()可以将json串转换为dict

{'name': 'liuyujing', 'age': '18'}

>>> s                                  #经过eval后的s没有什么变化

'{"name":"liuyujing","age":"18"}'

>>> print(type(eval(s)))                  #eval()可以将json串转换为dict

10、json编码

函数原型:

dumps(obj, skipkeys = False, ensure_ascii= True, check_circular=True, allow_nan = True, cls = None, indent = None, separators = None, encoding = “utf- 8”, default = None,sort_keys = False, **kw)

该方法返回编码后的一个json字符串,是一个str对象encodejson.

dumps函数的参数很多,但是不是所有的都必须弄清楚,下面只说明几个比较常用的参数。

1) sort_keys:

是否按字典排序(a到z)输出。因为默认编码成json格式字符串后,是紧凑输出,并且也没有顺序的,不利于可读。

>>> data = [{"a":"A","x":(2,4),"c":3.0,"b":"4"},]

>>> json.dumps(data)

'[{"a": "A", "x": [2, 4], "c": 3.0, "b": "4"}]'      #key值无顺序

>>> json.dumps(data,sort_keys =  True)  #按照key值排序输出,且也转化为Json字符

'[{"a": "A", "b": "4", "c": 3.0, "x": [2, 4]}]'      #串类型

>>> data = {1:2,53:4,5:6}

>>> json.dumps(data,sort_keys = True)

'{"1": 2, "5": 6, "53": 4}'                   #依然会按照key值排序

>>> data = {1:2,53:4,"a":6}               #key值存在两种类型

>>> json.dumps(data,sort_keys = True)

TypeError: '<' not supported between instances of 'str' and 'int'

#报错,在int与str之间无法比较<

>>> data = {"1":"2","53":4,"a":6}          #key值都是str,有数字也有字母

>>> json.dumps(data,sort_keys = True)

'{"1": "2", "53": 4, "a": 6}'                 #能够排序

>>> ord("53")

Traceback (most recent call last):

File "", line 1, in

TypeError: ord() expected a character, but string of length 2 found

TypeError: ord()期望得到一个字符,但是找到了长度为2的字符串

2) indent:

设置参数缩进显示的空格数。缩进显示使读起来更加清晰。

>>> data = {"1":"2","53":4,"a":6}

>>> json.dumps(data,sort_keys = True,indent = 3)  #无print.换行输出\n

'{\n   "1": "2",\n   "53": 4,\n   "a": 6\n}'

>>> print(json.dumps(data,sort_keys = True,indent = 3))

{

"1": "2",

"53": 4,

"a": 6

}                                             #有print,每层缩进3格

>>> data = {"1":"2","53":[1,2,3,4,5,6],"a":6}        #”53”key的值是一个数组

>>> print(json.dumps(data,sort_keys = True,indent = 3))  #设置输出每层缩进3

{

"1": "2",                                   #”1”,”a”,”53”是一层,

"53": [                                    #[1,2,3,4,5,6]是第二层

1,                                     #遇到{}[],会换行

2,

3,

4,

5,

6

],

"a": 6

}

3) separators:

separators:参数的作用是去掉逗号”,”和分号”;”后面的空格,从上面的输出结果都能看到”,”与”:”后面都有个空格,这都是为了美化输出结果的作用,但是在我们传输数据的过程中,越精简越好,冗余的东西全部去掉,因此就可以加上separators参数对传输的json串进行压缩。该参数是元祖格式的。

>>> data = {"1":"2","53":4,"a":6}

>>> json.dumps(data)

'{"1": "2", "53": 4, "a": 6}'                  #”:”和”,”后都有空格

>>> len(json.dumps(data))                #不去掉”:”和”,”后的空格,长度是27

27

>>> json.dumps(data,separators = (",",":"))

'{"1":"2","53":4,"a":6}'                     #json串进行了压缩,在”:”和”,”后都没有空格

>>> len(json.dumps(data,separators = (",",":")))#去掉空格,长度是22

22

#从结果看出,通过移除多余的空白字符,达到了压缩数据的目的。

#海量数据处理时,很重要,能省很多字节

>>> len(json.dumps(data,separators = (",")))

Traceback (most recent call last):

File "", line 1, in

File "D:\Python36\lib\json\__init__.py", line 238, in dumps

**kw).encode(obj)

File "D:\Python36\lib\json\encoder.py", line 154, in __init__

self.item_separator, self.key_separator = separators

ValueError: not enough values to unpack (expected 2, got 1)

#报错,separators后面必须俩参数

4) skipkeys:

在encoding过程中,dict对象的key只可以是基本数据类型(str,Unicode,int,long,float,bool,None),如果是其他类型,那么在编码过程中就会抛出TypeError的异常。skipkeys可以跳过那些非string对象的key的处理,就是不处理。

>>> data= [ { 'a':'A', 'b':(2, 4), 'c':3.0, (1,2):'D tuple' } ]

>>> print(u"不设置skipkeys 参数")

不设置skipkeys 参数

>>> try :

…     res1 = json.dumps(data)           #skipkeys参数默认为False时

… except Exception as e:

…     print(e)

keys must be a string

>>> print(u"设置skipkeys 参数")

设置skipkeys 参数

>>> print(json.dumps(data, skipkeys=True))   # skipkeys=True时

[{"a": "A", "b": [2, 4], "c": 3.0}]     #不处理key值是(1:2)的数据

#list,set,dict不能做字典的key,tuple和类的实例可以做字典的key,所以skipkeys基本也就是跳过了tuple和类的实例

>>> data = [{"sr":2,(1,2):1,p:1},1]

>>> json.dumps(data,skipkeys = True)

'[{"sr": 2}, 1]'

5) ensure_ascii:

表示编码使用的字符集,默认是True,表示使用ascii码进行编码。如果设置为False.就会以Unicode进行编码。由于解码json字符串时返回的就是Unicode字符串,所以可以直接操作Unicode字符,然后直接编码Unicode字符串,这样会简单些。

>>> json.dumps("中国")       #默认使用ascii码进行编码,中文不可直接使用

'"\\u4e2d\\u56fd"'

>>> json.dumps("中国",ensure_ascii = False)

'"中国"'                      #使用unicode进行编码,中文可以直接使用

11、将类对象(实例)编码成Json串

Python中的dict对象可以直接序列化为json的{},但是很多时候,可能用class表示对象,比如定义Employe类,然后直接去序列化就会报错。原因是类不是一个可以直接序列化的对象,但我们可以使用dumps()函数中的default参数来实现。

>>> json.dumps({1:2})        #Python中的dict对象可以直接序列化为json的{}

'{"1": 2}'

>>> json.dumps([{1:2}])       #注意区别以上的例子

'[{"1": 2}]'

import json

class Employee(object):      #定义类Employe

def __init__(self, name, age, sex, tel):

self.name = name

self.age = age

self.sex = sex

self.tel = tel

def obj_json(self, obj_instance): #定义方法obj_json,参数obj_instance,就是实例对象

return {

'name': obj_instance.name,

'age': obj_instance.age,

'sex': obj_instance.sex,

'tel': obj_instance.tel }

emp = Employee('Lily', 24, 'female', '18223423423')

print(json.dumps(emp, default = emp.obj_json))

# {"name": "Lily", "age": 24, "sex": "female", "tel": "18223423423"}

#emp实例首先使用emp.obj_json方法,拼成了一个dict,搞成了一个json串。

12、JSON反序列化为类对象

json串反序列化成类对象或者类的实例,使用的是loads方法中的object_hook参数来实现。

import json

class Employee(object):

def __init__(self, name, age, sex, tel):

self.name = name

self.age = age

self.sex = sex

self.tel = tel

emp = Employee('Lily', 24, 'female', '18223423423')

def jsonToClass(emp):   # jsonToClass是函数,不是方法,emp是dict,不是实例

return Employee(emp['name'], emp['age'], emp['sex'], emp['tel'])

json_str = '{"name": "Lucy", "age": 21, "sex": "female", "tel": "15834560985"}' #json串

e = json.loads(json_str, object_hook = jsonToClass)

json_str作为一个参数,先转化为字典,然后传递给jsonToClass,返回一个实例

print(e)

print(e.name)

#<__main__.Employee object at 0x0000020EC3C4E668>

#Lucy

小练习:

1. 匹配ip

ip = 0.0.0.0

每一位的数字的范围是0-255

首先分析ip地址的特征:255.255.255.255;
1位: 0-9             [0-9] \d
2位:10-99         [1-9]\d
2位以内:            [1-9]?\d
3位:100-199      1\d{2}
3位:200-249      2[0-4]\d
3位:250-255      25[0-5]

import re

pattern = r"\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(" \

r"?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b"

pattern = re.compile(pattern)

print(pattern.search("255.213.2.345"))

print(pattern.search("0.0.0.0").group())

print(pattern.search("2.0.0.0").group())

(?:)代表括号不代表分组,取消分组,使用group(1)是读不到分组的内容的。

import re

print(re.search("a(\d)c","a1c").group(1))

#1

print(re.search("a(?:\d)c","a1c").group(1))

#IndexError: no such group

\b匹配一个单词边界
(?:pattern)匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用或字符“(|)"来组合一个模式的各个部分是很有用。例如"industr(?:y|ies)"就是一个比"industry|industries"更简略的表达式。

{n}n是一个非负整数。匹配确定的n次。