Python学习之路(十一):基础知识之re模块

1.模块的功能:

  • 为了方便管理程序,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用。
  • 在Python中有许多模块,我们可以导入模块来提高自己的编程效率,也能够更好地实现程序的功能。

2.正则

正则是描述一类字符或者字符串的规则,嵌套在re模块中,如果导入re模块就是使用正则取匹配字符或字符串中的内容。

2.1 字符组

字符组:[] 写在中括号中的内容都可以出现在字符串中
[0-9] 匹配数字
[a-z] 匹配小写字母 ASCII码97-122
[A-Z] 匹配大写字母 ASCII码65-90
[a-zA-Z] 匹配大小写字母
[a-zA-Z0-9] 匹配大小写字母+数字
[a-zA-Z0-9_] 匹配数字字母下划线

2.2 元字符

  • \w 匹配数字字母下划线
  • \d 匹配所有的数字
  • \s 匹配所有的空白符 回车/制表符
  • \t 匹配一个制表符
  • \n 匹配回车
  • \W 匹配非字母数字下划线
  • \D 匹配非数字
  • \S 匹配非空白/回车/制表符
  • [\s\S]、[\d\D]、[\w\W]匹配所有的字符
  • ^ 匹配一个字符串的开始
  • $ 匹配一个字符串的结尾
  • .匹配除换行符以外的所有字符
  • [^]匹配非字符组内容,例如[^a]就是匹配字符串中不是a的内容
  • 有一些有特殊意义的元字符进入字符组会回复它本来的意义:. | [] () / ? -(在字符组中有特殊意义,需要转义)
  • a|b 或 符合a规则或者b规则的都可以匹配,如果a规则是b规则的一部分,且a规则比b规则更长,应当将a规则写在前面,将更复杂,更长的规则写在前面。

2.3 量词

  • {n}表示这个量词之前的字符出现n次
  • {n,}表示这个量词之前的字符至少出现n次
  • {n, m}表示这个量词之前的字符出现n-m次
  • ?表示匹配量词之前的字符出现0次或者1次 表示可有可无
  • +表示匹配量词之前的字符出现 1次或者多次
  • *表示匹配量词之前的字符出现0次或者多次

2.4 分组

  • 对于正则表达式而言,有时候我们需要进行分组,来整体约束某一字符出现的次数,如(\.[\w+])?

2.5 正则练习

 1 匹配整数 \d+
 2 匹配小数 \d+\.\d+
 3 匹配整数或者小数 \d+(\.\d+)?
 4 匹配身份证号码:[1-9]\d{16}[\dx]|[1-9]\d{14}
 5 匹配年月日 :^[1-9]\d{0,3}-(1[0-2]|0?[1-9])-(3[01]|[12]\d|0?[1-9])$
 6 匹配QQ号: [1-9]\d{4-11}
 7 11位电话号码:1[3-9]\d{9}
 8 匹配验证码:[\da-zA-Z]{4}
 9 匹配邮箱:[0-9a-zA-Z][\w\-.]+@[a-zA-Z.0-9\-]+(\.[a-zA-Z0-9\-]+)*\.[a-zA-Z0-9]{2,6}
10 匹配内层没有小括号的表达式:\([^()]\)

2.6 正则表达式的特点

正则表达式的匹配特点:贪婪匹配

  • 贪婪匹配会在允许的范围内取最长的结果
  • 非贪婪模式/惰性匹配:在量词的后面加上?即在范围内尽量少的匹配。

3.re模块

3.1 re模块功能之查找(使用模块前必须import re导入模块)

# findall
ret = re.findall('\d+', 'sjkdfa112shfa998')
print(ret)
# 结果:['112', '998']
# search
ret = re.search('\d+', 'sjkdfa112shfa998')
if ret:  # 这里的ret只是正则结果的内存地址
    print(ret.group())  # 通过ret.group()获取真正的结果
# 结果:['1', '1', '2', '9', '9', '8']
# match  从头开始匹配,相当于search中的正则表达式加上一个^
ret = re.match('\d', '122sjkdfashfa998')
print(ret)
# 结果:112

3.2 切分

s = 'adkf12fag34'
ret = re.split('\d+',s)
print(ret)
# 结果:['adkf', 'fag', '']

3.3 替换

1 # sub
2 ret = re.sub('\d+', 'H', 'alex83taibai40', 1)
3 print(ret)
4 # 结果:alexHtaibai40
# subn  返回一个元组,第二个元素是替换的次数
ret = re.subn('\d+', 'H', 'alex83taibai40')
print(ret)
# 结果:('alexHtaibaiH', 2)

3.4 编译

compile 节省使用正则表达式解决问题的时间,将正则表达式编译成字节码,在多次使用时不会多次编译。

1 ret = re.compile('\d+')
2 res = ret.findall('alex83taibai40')
3 res_1 = ret.findall('213afda324')
4 res_2 =ret.search('4343faag')
5 print(res, res_1, res_2)

3.5 finditer

# finditer 节省使用正则表达式解决问题的空间
ret = re.finditer('\d+', 'alex342fa5')
print(ret)
for i in ret:
    print(i.group())

4.分组在re模块中的使用

4.1 优先匹配分组中的内容

 1 import re
 2 s = '<a>wahaha</a>'
 3 ret = re.search('<(\w+)>(\w+)</(\w+)>',s)
 4 print(ret.group())  # 括号内默认为0,打印所有的结果
 5 print(ret.group(1))  # 数字参数代表的是取对应分组中的内容
 6 print(ret.group(2))
 7 print(ret.group(3))
 8 # 结果:
 9 <a>wahaha</a>
10 a
11 wahaha
12 a

4.2 findall中的分组优先:优先显示分组中的内容:

1 import re
2 ret = re.findall('\d+(\.\d+)?', '1.234*4.3')
3 print(ret)
4 # 结果:['.234', '.3']

findall中的分组优先:优先显示分组中的内容

1 import re
2 ret = re.findall('\d+(?:\.\d+)?', '1.234*4.3')
3 print(ret)
4 # 结果:['1.234', '4.3']

4.3 split中的分组

 1 import re
 2 s = 'adkf12fag34'
 3 ret = re.split('\d+',s)
 4 print(ret)
 5 
 6 s = 'adkf12fag34'
 7 ret = re.split('(\d+)',s)
 8 print(ret)
 9 
10 # 结果:
11 ['adkf', 'fag', '']
12 ['adkf', '12', 'fag', '34', '']

4.4 分组的命名

1 import re
2 s = '<a>wahaha</a>'
3 ret = re.search('>(?P<con>\w+)<',s)
4 print(ret.group(1))
5 print(ret.group('con'))
6 # 结果:
7 wahaha
8 wahaha
1 s = '<a>wahaha</b>'
2 pattern = '<(\w+)>(\w+)</(\w+)>'
3 ret = re.search(pattern, s)
4 print(ret.group(1) == ret.group(3))
5 # 结果:False

注:使用前面的分组,要求使用这个名字的分组和前面同名分组中的内容匹配的必须一致。

1 s = '<a>wahaha</b>'
2 pattern = '<(?P<tab>\w+)>(\w+)</(?P=tab)>'
3 ret = re.search(pattern, s)
4 print(ret)

4.5 正则的表达应该更精确

 1 ret = re.findall(r"\d+", "1-2*(60+(-40.35/5)-(-4*3))")
 2 print(ret)  # 结果将不应该匹配的小数也匹配出来了
 3 # 结果:['1', '2', '60', '40', '35', '5', '4', '3']
 4 
 5 # 应该精确取到整数
 6 ret = re.findall(r"\d+\.\d+|\d+", "1-2*(60+(-40.35/5)-(-4*3))")
 7 print(ret)
 8 # 结果:['1', '2', '60', '40.35', '5', '4', '3']
 9 
10 # 使用分组优先显示整数
11 ret = re.findall(r"\d+\.\d+|(\d+)", "1-2*(60+(-40.35/5)-(-4*3))")
12 ret.remove('')
13 print(ret)
14 # 结果:['1', '2', '60', '5', '4', '3']

 

猜你喜欢

转载自www.cnblogs.com/Studying-Du/p/12361056.html