已经把注释写的很清楚了
#! -*- coding: utf-8 -*-
"""
Author: ZhenYuSha
Create type_time: 2020-4-7
Info: 正则模块
-------------------- 1.元字符 --------------------
-----正则元字符------描述--------------------------------
. 匹配任意字符(不包括换行符)
^ 匹配开始位置,多行模式下匹配每一行的开始
$ 匹配结束位置,多行模式下匹配每一行的结束
* 匹配前一个元字符0到多次
+ 匹配前一个元字符1到多次
? 匹配前一个元字符0到1次
{m,n} 匹配前一个元字符m到n次
\\ 转义字符,跟在其后的字符将失去作为特殊元字符的含义,例如\\.只能匹配.,不能再匹配任意字符
[] 字符集,一个字符的集合,可匹配其中任意一个字符
| 逻辑表达式 或 ,比如 a|b 代表可匹配 a 或者 b
(...) 分组,默认为捕获,即被分组的内容可以被单独取出,默认每个分组有个索引,从 1 开始,按照"("的顺序决定索引值
(?iLmsux) 分组中可以设置模式,iLmsux之中的每个字符代表一个模式,用法参见 模式 I
(?:...) 分组的不捕获模式,计算索引时会跳过这个分组
(?P...) 分组的命名模式,取此分组中的内容时可以使用索引也可以使用name
(?P=name) 分组的引用模式,可在同一个正则表达式用引用前面命名过的正则
(?#...) 注释,不影响正则表达式其它部分,用法参见 模式 I
(?=...) 顺序肯定环视,表示所在位置右侧能够匹配括号内正则
(?!...) 顺序否定环视,表示所在位置右侧不能匹配括号内正则
(?<=...) 逆序肯定环视,表示所在位置左侧能够匹配括号内正则
(? 来选择分组
group([group1, ...]) 根据提供的索引或名字返回响应分组的内容,默认返回 start() 到 end() 之间的字符串, 提供多个参数将返回一个元组
groupdict([default=None]) 返回 返回一个包含所有匹配到的命名分组的字典,没有命名的分组不包含在内,key 为组名,value 为匹配到的内容,参数 default 为没有参与本次匹配的命名分组提供默认值
groups([default=None]) 以元组形式返回每一个分组匹配到的字符串,包括没有参与匹配的分组,其值为 default
span([group]) 返回指定分组的起止位置组成的元组,默认返回由 start() 和 end() 组成的元组
start([group]) 返回指定分组的开始位置,默认返回正则表达式所匹配到的第一个字符的索引
---------------- 4.re 内置对象用法 ---------------
-------------------- 5.分组用法 ------------------
5.1 正则表达式中用小括号 "(" 表示分组,按照每个分组中前半部分出现的顺序 "(" 判定分组的索引,索引从 1 开始,每个分组在访问的时候可以使用索引,也可以使用别名
s = 'Hello, Mr.Gumby : 2016/10/26'
p = re.compile("(?P\w+\.\w+).*?(\d+)(?#comment)")
m = p.search(s)
# 使用别名访问
print m.group('name')
# output> Mr.Gumby
# 使用分组访问
print m.group(2)
# output> 2016
5.2 也可能只是为了把正则表达式分组,而不需要捕获其中的内容,这时候可以使用非捕获分组
5.3 如果你在写正则的时候需要在正则里面重复书写某个表达式,那么你可以使用正则的引用分组功能,需要注意的是引用的不是前面分组的 正则表达式 而是捕获到的 内容,并且引用的分组不算在分组总数中
-------------------- 5.分组用法 ------------------
-------------------- 6.环视用法 ------------------
环视还有其他的名字,例如 界定、断言、预搜索等,叫法不一。
环视是一种特殊的正则语法,它匹配的不是字符串,而是 位置,其实就是使用正则来说明这个位置的左右应该是什么或者应该不是什么,然后去寻找这个位置。
环视的语法有四种,具体如下:
s = 'Hello, Mr.Gumby : 2016/10/26 Hello,r.Gumby : 2016/10/26'
# 不加环视限定
print re.compile("(?P\w+\.\w+)").findall(s)
# output> ['Mr.Gumby', 'r.Gumby']
# 环视表达式所在位置 左边为 "Hello, "
print re.compile("(?<=Hello, )(?P\w+\.\w+)").findall(s)
# output> ['Mr.Gumby']
# 环视表达式所在位置 左边不为 ","
print re.compile("(?\w+\.\w+)").findall(s)
# output> ['Mr.Gumby']
# 环视表达式所在位置 右边为 "M"
print re.compile("(?=M)(?P\w+\.\w+)").findall(s)
# output> ['Mr.Gumby']
# 环视表达式所在位置 右边不为 r
print re.compile("(?!r)(?P\w+\.\w+)").findall(s)
# output> ['Mr.Gumby']
-------------------- 6.环视用法 ------------------
"""
import re
def s_print(query, max_number=15):
"""格式打印"""
def is_chinese(word):
"""判断是否含中文"""
for ch in word:
if '\u4e00' <= ch <= '\u9fff':
return True
return False
def rule_print(word, chinese, fill=" "):
"""规则打印"""
if chinese:
return word + 2*(max_number - len(word))*fill
else:
return word + (max_number - len(word))*fill
return rule_print(query, is_chinese(query))
# return query.ljust(max_number+len(query), "*") # 中文有问题
# return "{:<{len}}\t".format(query, len=max_number - len(query.encode("GBK")) + len(query))
def find_it(re_rule, context):
"""查找结果"""
re_arr = re.findall(re_rule, context)
print("用户: %s 结果: %s" % (s_print(context), "不匹配" if re_arr == list() else "匹配"))
def print_result(re_rule, re_comp, string_list):
"""打印结果"""
print("------------------------------------------------------")
print("规则:", re_rule)
print("------------------------------------------------------")
for tmp in string_list:
find_it(re_comp, tmp)
if __name__ == '__main__':
str_list = ["我不知道为什么你可以进来?", "你认识她嘛?", "你知道嘛?", "不知道", "你知道不?"]
# 不包含"不",且包含"知道"(顺序的,"知道"后面的"不"不处理)
ru_1 = "[^不]+知道.*"
# 不包含("不"或者"否"),且包含"知道"(无顺序的)
ru_2 = "^(?!.*?(不|否))(?=.*?知道{1,}).+$"
re_1 = re.compile(ru_1)
re_2 = re.compile(ru_2)
print_result(ru_1, re_1, str_list)
print_result(ru_2, re_2, str_list)