正则表达式 Regular Expression
# 正则表达式 支持的所有元字符:
# . ^ $ * + ? {} [] \ | ()
# . 匹配任何一个字符(而不是标点符号) 。多行模式下\n除外。单行模式下.可以匹配\n
# \ 转义符,eg.想精确匹配"." 可以"\."
# \b 匹配一个位置(同 ^ $),单词的开始或结束
# \d 匹配任何一个十进制数字,相当于[0-9]
# \D 匹配任何一个非十进制数字,相当于[^0-9]
# \s 匹配任何一个空白字符,相当于[\t\n\r\f\v]
# \S 匹配任何一个非空白字符,相当于[^\t\n\r\f\v]
# \w 匹配任何一个字母数字字符,相当于[a-zA-Z0-9_]
# \w 匹配任何一个非字母数字字符,相当于[^a-zA-Z0-9_]
# [] 匹配任何一类字符
# eg.[abcd]将匹配 'a' 'b' 'c' 'd' 中的任意一个字符, [.?!] 匹配标点符号
# 可加"-"表示范围, eg.[a-d] 同 [abcd]
# * 重复匹配前面一个字符 "0-无穷多" 次(默认匹配尽可能长,*? 则匹配尽可能短), eg 1*2 可以匹配 2 12 112 1112 11112 111112 ...
# + 重复匹配前面一个字符 "1-无穷多" 次(默认匹配尽可能长,+? 则匹配尽可能短), eg 1+2 可以匹配 12 112 1112 11112 111112 ...
# ? 重复匹配前面一个字符 "0-1" 次(默认匹配尽可能长,?? 则匹配尽可能短), eg 1?2 可以匹配 2 12
# 还有一个作用: ?" 表示接下来匹配到 " 之后就不再继续匹配,这对于 "abc"."def" 这种只想拿到"abc" 的case很有用
# 这对于左右括号,左右引号之类的模式匹配很有用
# {} 重复匹配前面一个字符 指定范围 次(默认匹配尽可能长,{}? 则匹配尽可能短), 算上前一个字符一共
# eg.1{3}2 可以匹配 1112, 而 1{3,5}可以匹配1112 11112 111112, 1{3,}2 则可以匹配 1112 11112 111112 1111112 ...
# eg.\d{8} 可以匹配八个数字 -------------------------??? 八个不是九个
# ^ 多行模式下代表一行的起始,相当于是\n之后的那个字符,单行模式下代表整个字符串的开始。 放在[]中相当于取反[^x]
# $ 多行模式下代表一行的末尾,相当于是\n,单行模式下代表整个字符串的结束 eg.匹配一行就是 "^.*$" 不过python可以直接用split("\n")
# | 相当于或,任意一个正则表达式匹配上就算匹配上
# () 分组,告诉 {} 需要重复的target, 匹配之后的字串也会按照 组 的方式
# eg.匹配一个ip地址 (eg. 192.168.0.1):
# \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}
# (\d{1,3}\.){3}\d{1,3} #当获取了这个字串的时候,('192','168','0','1')会被组织成一个元组
#一个例子:提取存档的html文件中所有的网址
# http:// 开头,或者 https:// 开头,然后是任意一个字符,(重复任意次),网址一般被""包起来
import re
#1) re.I(re.IGNORECASE): 忽略大小写
#2) re.M(MULTILINE): 多行模式,改变’^’和’$’的行为
#3) re.S(DOTALL): 点任意匹配模式,改变’.’的行为
#4) re.L(LOCALE): 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定
#5) re.U(UNICODE): 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性
#6) re.X(VERBOSE): 详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释
p = re.compile('"https?://.*?"', re.IGNORECASE) # ?" 表示找到离前面一个"最近的"之后就不再继续匹配
#p = re.compile('"http://.*?"|"https://.*?"', re.I) # re.IGNORECASE 和 re.I 都表示忽略大小写
with open("/home/fang/桌面/demo.html") as fr:
doc = fr.read()
print(type(doc))
# findall() 找到所有匹配的字串,作为一个list返回
# search() 扫描字符串,找到RE匹配的位置(只返回第一个的位置)
# p.match(doc) 会返回一个match对象(不包含pattern应该返回None吧)
for i in p.findall(doc):
print (type(i), i)
除了上面 findall函数外,还有几个常用的:
re.match(pattern, string, flags=0)
或
rp = re.compile(pattern, re.I | re.S)
mobj = rp.match(string) #默认从 pos=0 出开始匹配,pos=0除匹配不上就认为匹配失败,endpos=len(string)为默认的停止匹配位置
rp = re.compile(pattern, re.I | re.S)
mobj = rp.search(string) #search 直接从给定字符串中查找匹配的位置,找到就直接返回不再继续查找了
rp = re.compile(pattern, re.I | re.S)
res = list(rp.finditer(string)) # 类似 search,不同的是是搜索全部,返回一个迭代器,这里直接转化为 MatchObject 组成的 list
返回 MatchObject
拿到 MatchObject(比如是 mobj),你可以:
使用 mobj.group()或 mobj.group(0) 获取匹配的字符串
使用 mobj.group(i)获取匹配字符串中的第i个子group(前提是 pattern 中有"(xx)"),或 mobj.groups() 获取子group组成的元组
使用 mobj.span() 获取匹配字符串位于原始字符串中的index,即 (start,end),或 单独使用 mobj.start() mobj.end()
content = "hello , this is a test string"
p = re.compile(r'\w*is', re.I)
for i in p.findall(content):
print(i) # 返回 this 和 is
for i in range(len(content)):
res = p.match(content,i) # 默认从pos=0开始匹配,pos=0处匹配不上就认为匹配失败,endpos=len(string)为默认的停止匹配位置
if res:
print("found,{},{}".format(res.group(),res.span()))
else:
print("not found at {}".format(i))
res = p.search(content) # search 直接从给定字符串中查找匹配的起始位置,找到就返回不再继续找了
if res:
print("found,{},{}".format(res.group(),res.span()))
else:
print("not found")
res = list(p.finditer(content)) # 返回所有匹配的位置 span()
print(res)
for i in res:
print("type {}, {}, {}".format(type(i), i, i.span()))
https://deerchao.cn/tutorials/regex/regex.htm
https://blog.csdn.net/m0_38109046/article/details/85070106