python3字符串正则匹配多个ipv4
在python中使用正则表达式需要import re模块。
Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。
构造ip匹配规则:
以.
做分割,每个字段允许范围为0~255。
(0、1、2、为百位)
根据分割图,可先将0~255分为两部分:0~199、200~255。
根据分割图2,可将200~255分为200~249、250~255。200~249可表示为当百位为2且个位为0~4时,个位可为0~9
;250~255可表示为当百位为2且十位为5时,个位为0~5
。
又根据ip的特征,前三个字段后面跟着符号.
,所以ip地址(假设为127.0.0.1)可分为127.0.0.
和0
综上构造正则表达式
0~199可表示为当百位为0或1时,个位与百位可为0~9
;
200~249可表示为当百位为2且个位为0~4时,个位可为0~9
;
250~255可表示为当百位为2且十位为5时,个位为0~5
。
则0~255的正则表达式为[01]?\d?\d|2[0-4]\d|25[0-5]
ip匹配正则表达式为
(([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5])
re模块匹配函数选择(各函数使用方法详见菜鸟教程)
re.compile(pattern[, flags])
:编译正则表达式,生成一个正则表达式( Pattern )对象,供其他匹配函数调用,使用此正则表达式。
re.match(pattern, string, flags=0)
:只能匹配第一个ip值(共1个值),且只要字符串第一个字符匹配不成功,match()就返回none。
re.search(pattern, string, flags=0)
:只能匹配第一个ip值(共1个值),与match()不同的是,可以在字符串任意位置匹配成功,返回第一个匹配成功的值。
re.findall(string[, pos[, endpos]])
:匹配所有ip值,返回一个list。
re.finditer(pattern, string, flags=0)
:匹配所有ip值,并把它们作为一个迭代器返回。
据上述,我选择findall()与finditer()函数,主要以findall()为例。
findall():
在使用此函数时,若在正则表达式中使用了()
,需注意:
使用()
时,findall函数只返回最边上
的()
里匹配的值,但是外面会作为规则匹配。且会根据()由外向内、从左至右
分别将每个()
里匹配成功的字符串做为返回的list里的一个元组值。
这么说可能很难明白,看实例:python3-findall()实测
先看例1:
import re
str = "127.0.0.1 a1.12.123.249 b256.2.2.2 c3.3.3.555 d1122.4.4.4 e5.5.5.1122 f127.0.0.1"
pi = re.compile(r'((([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5]))');
result2 = pi.findall(str);
for i in result2:
print (i[0]);
返回结果:
127.0.0.1
1.12.123.24
56.2.2.2
3.3.3.55
122.4.4.4
5.5.5.112
127.0.0.1
虽然匹配的结果都是正确的ip,但是很多时候,我们并不希望将3.3.3.555匹配成3.3.3.55,也不希望1122.4.4.4匹配成122.4.4.4。这可以通过\D
(非数字的字符)来排除,只有ip地址前后匹配不是数字才返回。\D
位于()
外,仅作为匹配规则。
例2:
import re
str = "127.0.0.1 a1.12.123.249 b256.2.2.2 c3.3.3.555 d1122.4.4.4 e5.5.5.1122 f127.0.0.1"
pi = re.compile(r'\D((([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5]))\D');
result2 = pi.findall(str);
for i in result2:
print (i[0]);
输出结果:
1.12.123.249
a1.2.123.249 b
仅匹配输出1.12.123.249
,并没有将\D
匹配的a
和 空格
输出。\D
位于()
外,仅作为匹配规则,不将匹配的字符输出。
但这里有个问题,127.0.0.1没匹配到,原因是127.0.0.1后面没有字符。这里存在IP地址在字符串第一个字符或最后一个字符匹配成功的问题,需要用^
或$
匹配。(注:代码量就增多了,如果你有好的方法,欢迎评论交流。)
例3:
import re
result_list = [];
str = "127.0.0.1 a1.12.123.249 b256.2.2.2 c3.3.3.555 d1122.4.4.4 e5.5.5.1122 f127.0.0.1"
#头
pi2 = re.compile(r'^((([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5]))\D');
result3 = pi2.findall(str);
for i in result3:
result_list.append(i[0]);
# print (i[0]);
#中
pi = re.compile(r'\D((([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5]))\D');
result2 = pi.findall(str);
for i in result2:
result_list.append(i[0]);
# print (i[0]);
#尾
pi3 = re.compile(r'\D((([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5]))$');
result4 = pi3.findall(str);
for i in result4:
result_list.append(i[0]);
# print (i[0]);
print(result_list);
输出结果:
['127.0.0.1', '1.12.123.249', '127.0.0.1']
finditer():
没有findall()
的()
外的仅作匹配规则这一特性
例4:
import re
result_list = [];
str = "127.0.0.1 a1.12.123.249 b256.2.2.2 c3.3.3.555 d1122.4.4.4 e5.5.5.1122 f127.0.0.1"
#头
pi2 = re.compile(r'^((([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5]))\D');
result3 = pi2.finditer(str);
for i in result3:
result_list.append(i.group());
# print (i[0]);
#中
pi = re.compile(r'\D((([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5]))\D');
result2 = pi.finditer(str);
for i in result2:
result_list.append(i.group());
# print (i[0]);
#尾
pi3 = re.compile(r'\D((([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5]))$');
result4 = pi3.finditer(str);
for i in result4:
result_list.append(i.group());
# print (i[0]);
print(result_list);
#finall_list=[];
#for i in result_list:
# finall_list.append(re.sub(r'[^\d.]','',i));
#print(finall_list);
输出结果:
['127.0.0.1 ', 'a1.12.123.249 ', 'f127.0.0.1']
#加上上述代码#号部分,新增输出['127.0.0.1 ', '1.12.123.249 ', '127.0.0.1']
例5:
import re
result_list = [];
str = "127.0.0.1 a1.12.123.249 b256.2.2.2 c3.3.3.555 d1122.4.4.4 e5.5.5.1122 f127.0.0.1"
pi = re.compile(r'((([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5]))');
result2 = pi.finditer(str);
for i in result2:
result_list.append(i.group());
# print (i[0]);
print(result_list);
输出结果:
['127.0.0.1', '1.12.123.24', '56.2.2.2', '3.3.3.55', '122.4.4.4', '5.5.5.112', '127.0.0.1']
例4 中使用了\D
,finditer()
将\D
进行匹配并输出(a1.12.123.249和f127.0.0.1);例5与例1效果相同,可以根据实际情况使用。
还是太年轻,时隔许久再来看自己的文章,发现自己看得都云里雾里了。已加以修改,若还有不明处,评论私信都可以,谢谢大家能看到这里。
(注:本人菜鸡,个人见解,如有错误,欢迎评论指出)