正则表达式系列01-域名/ip的正则表达式(python)

1. 域名的正则表达式

这一段正则应该能匹配到绝大多数的域名,但并不能保证都没问题哦。

domain_regex = r'^([a-zA-Z0-9]([a-zA-Z0-9-_]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,11}$'

分析域名的正则表达式,

[a-zA-Z0-9] 这是匹配大小写字母和数字
[a-zA-Z0-9-_] 这是匹配大小写字母、数字和'-''_'
# 先分析前面这一节
[a-zA-Z0-9] 的意思是,因为域名开头只能是 大小写字母和数字
([a-zA-Z0-9-_]{0,61}[a-zA-Z0-9])? 的意思是,这一段可以出现0次或1次
\. 的意思是,转义.() 表示这就是一个字符串的.(),而不是正则表达式中的表任意字符的.()
# 然后这是域名的前段,这一部分可以出现1次或无数次
[a-zA-Z]{2,11} 的意思是,顶级域名只能由大小写字母组成,不能出现其他字符。

2. ip的正则表达式

ip_regex = r'^((25[0-5]|2[0-4]\d|1\d{2})|([1-9]?[1-9]))\.(((25[0-5]|2[0-4]\d|1\d{2})|([1-9]?\d))\.){2}((25[0-5]|2[0-4]\d|1\d{2})|([1-9]?\d))$'

分析ip的正则表达式,

# ip的情况就要分得更细一点了。
# 首先ip分为4段,第一段可能出现的数字都是在1~255这个范围内。
# 剩余3段可能出现的数字都是在0~255这个范围内。

首先,考虑ip的第一段。

  1. 首先考虑数字是3位数的情况:

若是25x,那么这个x只能取0-5.
若是2xy,那么这个x可以取0-4,y可以取0-9。
若是1xy,那么这个x可以取0-9,y可以取0-9。

  1. 然后考虑数字是2位数的情况:
    开头数字不能是0,若是xy,x可以取1-9,y可以取0-9。
  2. 最后考虑数字是1位数的情况:
    开头数字不能是0,只能是x,x可以取1-9。

然后,考虑ip的剩余3段,这3段可能出现的数字是一样的。

先比与ip的第一段,唯一不同地方就在于,这3段是可以出现0的!!!其余并无不同。

根据上边的规则,写出了如下的正则表达式:

25x的正则表达式:25[0-5]
2xy的正则表达式:2[0-4]\d
1xy的正则表达式:1\d{2}
xy或x的正则表达式是在一起的:[1-9]?\d,这个包含了取到0的情况。
因此,ip的第一段中取得xy或x的正则表达式是:[1-9]?[1-9]
将上述这些组合起来就是:
ip第1段:((25[0-5]|2[0-4]\d|1\d{2})|([1-9]?[1-9]))\.)
ip后2段:(((25[0-5]|2[0-4]\d|1\d{2})|([1-9]?\d))\.){2}
ip最后一段:((25[0-5]|2[0-4]\d|1\d{2})|([1-9]?\d))

需要注意的是,这个ip的正则表达式没有去除127.0.0.1,也没有去除255.x.x.x这类的ip,可以根据实际业务需求进行适当地调整。

3. re模块

3.1 re.compile()

re.compile() # 编译正则表达式为正则表达式(Parttern)对象。生成的对象供re.match()和re.search()使用。
re.compile(pattern[, flags])
返回值:我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。

参数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 为了增加可读性,忽略空格和 # 后面的注释

用法:
import re
pattern = re.compile(r'\d+') # 用于匹配至少一个数字

3.2 re.match()

re.match() # 从头开始匹配正则表达式
re.match(pattern, string, flags=0)
返回值:我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。

参数pattern:指编译之后的正则表达式
参数string:指需要进行匹配的字符串
参数flag:用于控制正则表达式的匹配方式。可选的参数有:

re.I 使匹配对大小写不敏感
re.L 做本地化识别(locale-aware)匹配
re.M 多行匹配,影响 ^ 和 $
re.S 使 . 匹配包括换行在内的所有字符
re.U 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
re.X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。

用法:
import re
line = "Cats are smarter than dogs"
 
matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)
 
if matchObj:
   print("matchObj.group() : ", matchObj.group())
   print("matchObj.group(1) : ", matchObj.group(1))
   print("matchObj.group(2) : ", matchObj.group(2))
else:
   print("No match!!")

# 输出
matchObj.group() :  Cats are smarter than dogs
matchObj.group(1) :  Cats
matchObj.group(2) :  smarter

3.3 re.search()

re.search() # 获得匹配正则表达式的第一个结果
re.search(pattern, string, flags=0)

参数 pattern:匹配的正则表达式
参数 string:要匹配的字符串。
参数 flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。此参数的值与re.match()是一样的。
返回值: 匹配成功re.search方法返回一个匹配的对象,否则返回None。
我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。

用法:
import re
 
line = "Cats are smarter than dogs";
 
searchObj = re.search( r'(.*) are (.*?) .*', line, re.M|re.I)
 
if searchObj:
   print("searchObj.group() : ", searchObj.group())
   print("searchObj.group(1) : ", searchObj.group(1))
   print("searchObj.group(2) : ", searchObj.group(2))
else:
   print("Nothing found!!")

# 输出
searchObj.group() :  Cats are smarter than dogs
searchObj.group(1) :  Cats
searchObj.group(2) :  smarter

3.4 re.findall()

re.findall() # 获得满足正则表达式的所有结果
findall(string[, pos[, endpos]])

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

用法:
import re
 
pattern = re.compile(r'\d+')   # 查找数字
result1 = pattern.findall('runoob 123 google 456')
result2 = pattern.findall('run88oob123google456', 0, 10)
 
print(result1)
print(result2)

# 输出
['123', '456']
['88', '12']

3.5 re.finditer()

re.finditer() # 获得满足正则表达式的所有结果,返回数据为一个迭代器
re.finditer(pattern, string, flags=0)

参数 pattern:匹配的正则表达式
参数 string:要匹配的字符串。
参数 flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。此参数的值与re.match()是一样的。
返回值: 匹配成功re.search方法返回一个匹配的对象,否则返回None。
我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。

用法:
import re
 
it = re.finditer(r"\d+","12a32bc43jf3") 
for match in it: 
    print (match.group())

# 输出
12 
32 
43 
3

3.6 re.split()

re.split() # 已多个分隔符分隔字符串
re.split(pattern, string[, maxsplit=0, flags=0])

参数 pattern:匹配的正则表达式
参数 string:要匹配的字符串。
参数 maxsplit:分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数。
参数 flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。与re.mach()的番薯flags是一样的。

>>>a='w w w'

>>>import re

1.空格分

>>>re.split(r'[\s]',a)

['w','w','w']

2.只分割一次

>>>re.split(r'[\s]',a,1)

['w','ww']

3.多个字符分割

>>>c='w!w@w%w^w'

>>>re.split(r'[!@%^],c)

['w','w','w','w','w']

4.还原?:

>>>re.split(r'(?:!@%^),c)

['w!w@w%w^w']

3.7 re.sub()

re.sub() # 替换匹配到的字符串
re.sub(pattern, repl, string, count=0, flags=0)

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

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

# 输出
电话号码是:  2004-959-559 
电话号码是 :  2004959559

4. 正确理解正则表达式中原始字符串的作用

原始字符串只是避免了对字符串转义这一步,在正则表达式中使用了原始字符串之后,仍然需要对某些特殊字符转义,例如:

.    \     ?     *     + 等等

5. 参考文献

[1] 菜鸟教程
[2] python cookbook
[3 ] Python正则表达式-为什么要用原始字符串
[4] Python: str.split()和re.split()的区别

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值