昨天做网页爬取的时候,感觉自己对正则不熟悉的很,故今天再花上午时间认真整理下,不可懈怠。
1.常见正则表达式符号
[1].literal 匹配文本字符串的字面值literal
[2].re1|re2 匹配正则表达式re1或者re2 foo | bar
[3].. 匹配任何字符(除\n) b.b
[4].^ 匹配字符串的起始部分 ^Dear
[5].$ 匹配字符串的终止部分 /bin/*sh$
[6].* 匹配0次或多次前面出现的正则表达式 [A-Za-z0-9]*
[7].+ 匹配1次或者多次前面出现的正则表达式 [a-z]+\.com
[8].? 匹配0次或1次前面出现的正则表达式 goo?
[9].{N} 匹配N次前面出现的正则表达式 [0-9]{3}
[10].{M,N} 匹配M~N次前面出现的正则表达式 [0-9]{5,9}
[11].[...] 匹配来自字符集的多个字符 [aeiou]
[12].[..x-y..] 匹配x-y范围内的任意单一字符 [0-9a-zA-Z]
[13].[^...] 不匹配此字符集中出现的任何一个字符,包括某一范围内的字符 [^fsdlkj] [^a-z]
[14].(*|+|?|{})? 用于匹配上面频繁出现的符号的非贪婪版本 .*?[a-z]
[15].(...) 匹配封闭的正则表达式,然后另存为子组 ([0-9]{3})?, f(oo|u)bar
2.特殊字符
[1].\d 匹配任何十进制数字,与[0-9]一致(\D表示不匹配任何非数值型的数字) data\d+.txt
[2].\w 匹配任何字母数字字符,与[0-9a-zA-Z]相同(\W与之相反) [A-Za-z]\w+
[3].\s 匹配任何空格字符(\S与之相反) of\sthe
[4].\b 匹配任何单词边界(\B与之相反) \bThe\b
[5].\Number 匹配已保存的子组Number price:\16
[6].\c 仅按字面意思匹配,不匹配特殊含义 \., \\, \*
[7].\A(\Z) 匹配字符串的开始(结束) \ADear
3.使用圆括号指定分组
有些时候,我们不仅对之前匹配成功的数据更感兴趣,而且想要知道能否提取任何已经匹配成功的特定字符串或者子字符串。为了解决这个问题,只要用一对圆括号包裹任何正则表达式。
当使用圆括号时,一对圆括号可以实现以下任意一个功能:1)对正则表达式进行分组;2)匹配分组。
\d+(\.\d*)? 表示简单浮点数的字符串,也就是说,任何十进制数字,后面可以接一个小数点和零个或者多个十进制数字,例如"0.004","2","75."
(Mr?s?)?[A-Z][a-z]*[A-Za-z-]+ 名字和姓氏,以及对名字的限制(如果有,首字母必须大写,后续字母小写),全名前可以有可选的"Mr.","Mrs.","Ms."或者"M."作为称谓,以及可选的姓氏,可以有多个单词、横线以及大写字母。
4.re模块核心函数和方法
[1].仅仅是re模块函数
compile(pattern, flags=0) 使用任何可选的标记来编译正则表达式的模式,然后返回一个正则表达式对象
[2].re模块和正则表达式对象的方法
match(pattern, string, flags=0) 尝试使用带有可选的标记的正则表达式的模式来匹配字符串。如果匹配成功,就返回匹配对象,如果失败,就返回None。
search(pattern, string, flags=0) 使用可选标记搜索字符串中第一次出现的正则表达式的模式来搜索字符串,如果搜索成功,则返回匹配的字符串;否则返回None
findall(pattern, string[,flags]) 查找字符串中所有(非重复)出现的正则表达式模式,findall方法总是返回一个列表,如果匹配成功,列表将包含所有成功匹配的部分(从左向右顺序排列),如果失败则返回一个空列表。
子组在一个更复杂的返回列表中搜索结果,而且这样做是有意义的,因为子组是允许从单个正则表达式中抽取特定模式的一种机制。
Example:
# 使用findall和finditer查找每一次出现的位置
s = 'This and that and This and that'
lists = re.findall(r'(th\w+) and (th\w+)', s, re.I)
print(lists)
Result:
[('This', 'that'), ('This', 'that')]
finditer(pattern, string[, flags]) 与findall函数相同,但返回的不是一个列表,而是一个迭代器。它的优点在于更节省内存资源。
iters = pattern.finditer('dottt0999-ewar3223--AAnot333423-fsd-0')
for iter in iters:
print(iter.group())
split(pattern, string, max=0)
sub(pattern, repl, string, count=0) 使用repl替换所有正则表达式的模式在字符串中出现的位置,除非定义count,否则将替换所有出现的位置
[3].常见的匹配对象方法
group(num=0) 返回整个匹配对象,或者编号为num的子组
groups(default=None) 返回一个包含所有匹配子组的元组(如果没有成功匹配,则返回一个空元祖)
groupdict(default=None) 返回一个包含所有匹配的命名子组的字典,所有的子组名称作为字典的键(如果没有成功匹配,就返回一个空字典)
groupdict看似很难,但通过例子可以相当便利的理解:
Example:
match = re.search(r'\((?P
'(800) 555-1212')
print( match.groupdict() )
Result:
{'prefix': '555', 'areacode': '800'}
意思是,如果给分组起了别名,那么在groupdict中就会显示以别名为键,正则模式匹配字符为值的字典。
[4].常用的属性模块
re.I 不区分大小写的匹配
re.L 根据所使用的本地语言环境通过\w,\W,\b,\B,\s,\S实现匹配
re.M ^和$分别匹配目标字符串中的行的起始和结尾,而不是严格匹配整个字符串本身的起始和结尾。
re.S '.'号通常匹配除了\n之外的所有单个字符;该标记表示'.'号能够匹配全部字符
5.常见用法:
[1].匹配多个字符串
bt = 'bat|bet|bit'
m = re.match(bt, 'bat')
if m is not None:
print(m.group())
[2].特殊含义的字符匹配
., *, ?, (, ), +, ... 这些字符都需要转义后才能匹配字符串中原有字符。
比如字符串为[email protected],那么需要使用(\w+)@(\w+)\.com才能匹配,注意其中的.的转义。
[3].从单个正则表达式中抽取特定模式(使用分组)
例如我们想要匹配一个完整电话号码中的一部分,例如区号; 或者完整电子邮件地址的一部分,例如登录名称。
Example:
s = 'This and that'
print( re.findall(r'(th\w+) and (th\w+)', s, re.I) )
Result:
[('This', 'that')]
[4].将美式的日期表示法MM/DD/YY{,YY}格式转换为其他国家常用的格式DD/MM/YY{,YY}
可以使用\N取出匹配分组,其中N是在替换字符串中使用的分组编号。
很奇怪:
s = "i love you so dont let me upset"
lists = re.findall(r'(?#This is wonderful)(?P
的结果为什么是:['i love', ' you', ' so', ' dont']呢?为什么是'i love'?