Python-7-Python正则表达式
7-1 初识正则表达式
通俗而言,就是通过某种规则,来匹配符合条件的字符序列。适用场景:快速查找、替换、匹配具有特殊格式的字符,如 文本替换、匹配电子邮箱、电话号码、IP地址等。匹配爬虫程序中某些特殊字符。
格式:
import re re.findall(pattern, string, flags=0) #会将所有符合条件的字符放在一个列表中
其中:
pattern 是正则表达式的匹配规则
string 是要进行匹配的字符串
flags 是可选参数,进行特定条件的匹配。
例子:
#匹配字符串中所有的lemon. import re match_str = 'lemon&apple&lemoon&banana&lemooon&pear&lemoooon' re.findall('lemon', match_str) ----------------------- ['lemon'] #选出 lemon lemoon lemooon lemoooon import re match_str = 'lemon&apple&lemoon&banana&lemooon&pear&lemoooon' re.findall('lemo{1,4}n', match_str) ----------------------- ['lemon', 'lemoon', 'lemooon', 'lemoooon']
7-2 字符集
例子:
import re match_str = 'bac | bbc | bcc | bdc | bec' re.findall('b[ab]c', match_str) #匹配以b开头以c结尾,中间是a或b的字符串 ----------------------- ['bac', 'bbc'] re.findall('b[^ab]c', match_str) # ['bcc', 'bdc', 'bec'] 匹配中间非ab的字符串 re.findall('b[a-d]c', match_str) # ['bac', 'bbc', 'bcc', 'bdc'] 匹配中间a-d的字符串 re.findall('b[^a-d]c', match_str) # ['bec'] 取反操作,不匹配中间是a-d的字符串
7-3 常见元字符
所有的元字符见:https://tool.oschina.net/uploads/apidocs/jquery/regexp.html
讲解3个常见的元字符:
(1) 数字字符,如”\d 匹配一个数字字符。等价于[0-9]"。"\D 匹配一个非数字字符。等价于[^0-9]"。
(2) 单词字符,如"\w 匹配包括下划线的任何单词字符。等价于“[A-Za-z0-9_]”","\W 匹配任何非单词字符。等价于“[^A-Za-z0-9_]"。
(3) 空白字符,如"\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]","\S 匹配任何非空白字符。等价于[^ \f\n\r\t\v]"。
(4) 点字符(.),匹配除"\n"之外的任何带个字符。
例子:
#数字字符 import re match_str = 'l&a0b1c2d3e4f5%~' re.findall('\d', match_str) #['0', '1', '2', '3', '4', '5'] re.findall('\D', match_str) #['l', '&', 'a', 'b', 'c', 'd', 'e', 'f', '%', '~'] #单词字符 import re match_str = 'l&a0b1c2d3e4f5%~' re.findall('\w', match_str) #['l', 'a', '0', 'b', '1', 'c', '2', 'd', '3', 'e', '4', 'f', '5'] re.findall('\W', match_str) #['&', '%', '~'] #空白字符 空格、制表符、换页等 import re match_str = 'l&a0\nb1c2\rd3e4\tf 5%~' re.findall('\s', match_str) #['\n', '\r', '\t', ' '] re.findall('\S', match_str) ----------------------- ['l', '&', 'a', '0', 'b', '1', 'c', '2', 'd', '3', 'e', '4', 'f', '5', '%', '~'] #点字符(.) import re match_str = '\n123 abc\r' re.findall('.', match_str) #['1', '2', '3', ' ', 'a', 'b', 'c', '\r'] re.findall('.', match_str, re.S) #['\n', '1', '2', '3', ' ', 'a', 'b', 'c', '\r'] re.S让'.'也可以匹配'\n'
7-4 数量词
取出完整的数字集合,如 123,34
1. 取出数字集合
#匹配字符,1-3次后输出 import re match_str = '&a0b12c344d55&AC_' re.findall('\d{1,3}', match_str) #['0', '12', '344', '55'] 1,,3中间不能有空格 re.findall('\d{1,}', match_str) # '0', '12', '344', '55'] 匹配1-n次 #匹配数字 import re match_str = '&a0b12c344d55&AC6789_' re.findall('\d{1,3}', match_str) # ['0', '12', '344', '55', '678', '9'] re.findall('\d{1,}', match_str) # ['0', '12', '344', '55', '6789'] 用{1,}匹配数字好一些
2. 取出单词集合
import re match_str = '&lemon12banana34pear@56' re.findall('[a-z]{4,6}', match_str) #['lemon', 'banana', 'pear'] 匹配a-z的任意字符4-6次 #匹配所有长度 match_str = '&lemon12banana34pear@56watermallon' re.findall('[a-z]{4,}', match_str) # ['lemon', 'banana', 'pear', 'watermallon']
指定了匹配4-6次,为啥匹配了4次后还没停下来呢,因为贪婪匹配,匹配范围内最大的长度。
7-5 贪婪与非贪婪
贪婪:倾向于最大长度匹配
非贪婪:倾向于最小长度匹配
例子:
import re match_str = '&lemon12banana34pear@56watermallon' re.findall('[a-z]{4,6}?', match_str) #['lemo', 'bana', 'pear', 'wate', 'rmal'] '?'表示非贪婪,只匹配4-5中最小的长度 re.findall('[a-z]{4}?', match_str) #['lemo', 'bana', 'pear', 'wate', 'rmal'] 和上面等效 import re match_str = 'lemooooon' re.findall('lemo{1,}', match_str) # ['lemooooo'] 贪婪匹配,匹配出所有长度 re.findall('lemo{1,}?', match_str) #['lemo'] 非贪婪匹配,能匹配成功的情况下尽可能的少匹配。一个字符也没多
7-6 次数匹配
数量词:
* 代表匹配前面字符0次或多次 {0,}。
+ 代表匹配前面字符1次或多次 {1,}。
? 代表匹配前面字符0次或1次 {0,1}。
例子:
import re match_str = 'lemo123, lemon345, lemonnnn567' re.findall('lemon*', match_str) #['lemo', 'lemon', 'lemonnnn'] 匹配前面的'n'字符0次或多次 re.findall('lemon+', match_str) #['lemon', 'lemonnnn'] re.findall('lemon?', match_str) #['lemo', 'lemon', 'lemon']
7-7 定位符
定位符用于匹配字符串的边界,有两个常用定位符:
^ 匹配字符串开始位置
$ 匹配字符串结尾位置
例子:
import re match_str = 'abcdef 123456 abcdef 456 abc' # match_str 是一个字符串 re.findall('^[a-z]{6}', match_str) #['abcdef'] #匹配小写字母开始,直到空格,匹配6位 re.findall('[a-z]{3}$', match_str) #['abc']
[^abc] 是取反的意思,表示不去匹配abc,^在中括号里面与外面是完全不一样的含义。
7-8 组的匹配
一组字符的集合,使用的是小括号。
例子:
import re match_str = 'lemonlemonlemonappleappleapplepearpear' #re.findall('(lemon){3}', match_str) #['lemon'] findall()会对多个组有一个去重的操作 re.search('(lemon){3}', match_str).group() #'lemonlemonlemon' 和这个不会去重
注:(lemon) 匹配 lemon 这一组字符,[lemon] 匹配中括号中的任意一个字符。
import re match_str = 'lemonpear' re.findall('[lemon]{3}', match_str) #['lem'] re.findall('(lemon)', match_str) #['lemon']
7-9 flags 可选参数
格式:
re.findall(pattern, string, flags=0)
例子:
import re match_str = 'lemon LEMON' re.findall('lemon', match_str) #['lemon'] 默认是区分大小写的 re.findall('lemon', match_str, re.I) #['lemon', 'LEMON'] re.I 让其不区分大小写 import re match_str = 'lemon\n LEMON\n' re.findall('lemon.', match_str, re.I|re.S) #['lemon\n', 'LEMON\n'] 让不区分大小写,且同时匹配\n
7-10 match 与 search函数
函数格式:
re.findall(pattern, string, flags=0) #搜索整个字符串,返回说有匹配组 re.match(pattern, string, flags=0) #从字符串首字符开始匹配,若首字符不匹配则返回None,若匹配则返回第一个匹配对象。 re.search(pattern, string, flags=0) #搜索整个字符串,若全都不匹配则返回None,若匹配则返回第一个匹配对象。
例子:
import re match_str = '5678 lemon 1234' re.findall('\d', match_str) #['5', '6', '7', '8', '1', '2', '3', '4'] re.match('\d', match_str).group() #'5' 若没匹配到使用group解引用报错 re.match('\d', match_str) #<re.Match object; span=(0, 1), match='5'> re.search('\d', match_str).group() #'5' re.search('\d', match_str) #<re.Match object; span=(0, 1), match='5'>
7-11 group 组匹配
例子:
import re match_str = 'life is mostly happly, but sometimes sad' #需求1:将"is mostly happly, but sometimes"匹配出来 r = re.search('life(.*)sad', match_str) #'.'表示除了换行符之外任何单个字符都可以匹配,'*'代表匹配前面的字符0次或多次 r #<re.Match object; span=(0, 40), match='life is mostly happly, but sometimes sad'> 匹配的对象、范围、字符串 r.group() #'life is mostly happly, but sometimes sad' 不传参数等于传0 r.group(0) #'life is mostly happly, but sometimes sad' r.group(1) # ' is mostly happly, but sometimes ' #需求2: 将"is mostly happly"和"sometimes"匹配出来 r = re.search('life(.*)but(.*)sad', match_str) r #<re.Match object; span=(0, 40), match='life is mostly happly, but sometimes sad'> r.group() #'life is mostly happly, but sometimes sad' r.group(1) #' is mostly happly, ' 匹配第一个分组的字符串 r.group(2) #' sometimes ' 匹配第二个分组的字符串
注:match_str必须得是在一行,否则查找不到!
7-12 正则替换
1. sub()
re.sub(pattern, rep1, string, count=0, flags=0)
pattern 正则表达式
rep1 要替换的内容,也可以传入函数
string 被替换的字符串
count 默认为0,代表全部替换。1代表替换1次,2代表替换2次,依次类推。
例子:
#需求1:将lemon都替换为a import re match_str = 'lemon apple lemon pear' re.sub('lemon', 'a', match_str, count=0) #'a apple a pear' re.sub('lemon', 'a', match_str, count=1) #'a apple lemon pear' 只替换一次 #需求2:数字小于7的都转换为0,大于等于7的都转换为10 import re match_str = 'lemon apple 123456789 lemon pear' def transform(value): pass re.sub('\d', transform, match_str, count=0) #'lemon apple lemon pear' 可以发现1-9给全部替换了 ========================== import re match_str = 'lemon apple 123456789 lemon pear' def transform(value): print(value) re.sub('\d', transform, match_str, count=0) ------------------------- <re.Match object; span=(12, 13), match='1'> #可以看到value是一个对象 <re.Match object; span=(13, 14), match='2'> <re.Match object; span=(14, 15), match='3'> <re.Match object; span=(15, 16), match='4'> <re.Match object; span=(16, 17), match='5'> <re.Match object; span=(17, 18), match='6'> <re.Match object; span=(18, 19), match='7'> <re.Match object; span=(19, 20), match='8'> <re.Match object; span=(20, 21), match='9'> 'lemon apple lemon pear' ========================== #通过返回函数,可以实现更新复杂的逻辑判断 import re match_str = 'lemon apple 123456789 lemon pear' def transform(value): match_num = value.group() if int(match_num) < 7: #可以使用type(match_num)查看类型为str,不能直接和数字比较大小 return '0' else: return '10' print(type(match_num)) re.sub('\d', transform, match_str, count=0) #'lemon apple 000000101010 lemon pear'
这里允许用户提供一个接口,是允许用户自己实现替换逻辑的。
posted on 2023-08-01 15:22 Hello-World3 阅读(26) 评论(0) 编辑 收藏 举报