匹配过程:
首先由 正则表达式 构造 NFA,再由NFA 转化成 DFA
在python中需要引入re模块
表示字符:
. 匹配任意一个字符(除了\n)
In [5]: re.match("...", "ab") #匹配三个字符 In [6]: re.match("...", "abc") Out[6]: <_sre.SRE_Match at 0x7f90a947bf38>
\d表示是阿拉伯数字, \D表示不是数字
In [7]: re.match("\d", "2") Out[7]: <_sre.SRE_Match at 0x7f90a956f6b0> In [8]: re.match("\D","a") Out[8]: <_sre.SRE_Match at 0x7f90a948db28>
\s匹配空白,即空格,tab, \S匹配非空白
\w匹配单词字符,即a-z, A-Z, 0-9, _ \W 匹配非单词字符
[ ]表示可以选择[]里面的内容, [^]表示不是集合里面的
^在正则中有两种含义:1是表示字符串的开头,2是表示否定,[]表示是字符集,^只有在字符集中才表示否定
In [10]: re.match("1[345678]", "18") Out[10]: <_sre.SRE_Match at 0x7f90a948dac0> In [11]: re.match("1[345678]", "19") In [12]: re.match("1[^345678]", "19") Out[12]: <_sre.SRE_Match at 0x7f90a948db90>
数量:
* 匹配前一个字符次数 >= 0
+ 匹配前一个字符次数 >=1
? 匹配前一个字符出现一次或者0次
{m} 字符出现m次
{m,} 匹配前一个字符至少m次
{m, n}匹配前一个字符m到n次
表示边界:
^匹配字符串开头
$匹配字符串结尾
\b匹配一个单词的边界
In [32]: re.match(r"^\w+ve\b", "hover") #ve在边界 In [33]:
In [33]: re.match(r"^\w+\s\bve\b", "ho ve r") Out[33]: <_sre.SRE_Match at 0x7f90a949d168>
nI [34]: re.match(r"^.+\bve\b", "ho ve r") Out[34]: <_sre.SRE_Match at 0x7f90a949d1d0>
\B表示匹配非单词边界
In [35]: re.match(r"^.+ve\B","ho ver") Out[35]: <_sre.SRE_Match at 0x7f90a949d238>
示例:
匹配0-100之间的数字
In [38]: re.match(r"[1-9]\d?$|0$|100$", "1") Out[38]: <_sre.SRE_Match at 0x7f90a949d370>
可以优化一下,对于0的情况
In [43]: re.match(r"[1-9]?\d?$|100$", "2")
Out[43]: <_sre.SRE_Match at 0x7f90a949d4a8>
#提取内容 In [45]: result = re.match(r"<h1>(.*)</h1>", "<h1>匹配分组</h1>") In [46]: result.group() Out[46]: '<h1>\xe5\x8c\xb9\xe9\x85\x8d\xe5\x88\x86\xe7\xbb\x84</h1>'
\num 引用分组num匹配到的字符串
s = <html><h1>itcats</h1></html> In [55]: re.match(r"<(.+)><(.+)>.+</\2></\1>", s) Out[55]: <_sre.SRE_Match at 0x7f90a9478c68>
匹配邮箱,并取出邮箱账号
In [60]: result = re.match(r"(\w+)@(qq|123|126|gmail).(com|cn|net)", s) In [61]: result.group(1) Out[61]: '1204177244'
?P<name>分组起名
?P=name
In [72]: s = "<html><h1>itcast</h1></html>" #为提取的字段起一个别名,当用这个字段时, (?P=name) In [73]: result = re.match(r"<(?P<key1>.+)><(?P<key2>.+)>.+</(?P=key2)></(?P=key1)>", s) In [74]: result.group() Out[74]: '<html><h1>itcast</h1></html>' In [75]: result.group(1) Out[75]: 'html' In [76]: result.group(2) Out[76]: 'h1' In [77]: result.group(3)
search对字符串整个进行搜索,只会拿到第一个, find_all
In [78]: s Out[78]: '<html><h1>itcast</h1></html>' In [79]: re.search(r"itcast", s) Out[79]: <_sre.SRE_Match at 0x7f90a949d6b0> In [80]: re.search(r"^itcast$", s)
sub 将匹配到的数据进行替换, (匹配规则, 替换内容, 源串)
In [81]: re.sub(r"php", "python", "itcast python cpp php python php") Out[81]: 'itcast python cpp python python python'
In [83]: def replace(result): ....: print(result.group()) ....: r = int(result.group())+50 ....: return str(r) ....: In [84]: re.sub(r"\d+", replace, "python=1000,php=0") 1000 0 Out[84]: 'python=1050,php=50'
去掉html中的标签 In [85]: re.sub(r"</?\w+>", "", s)
split 根据匹配进行切割字符串,并返回一个列表
In [93]: re.split(r":|,|-", s)
贪婪模式
在匹配过程中一旦前面内容匹配会一直往后匹配
In [7]: s = "this is a number 234-235-22-423" #匹配 .+ 会一直往后匹配,直到只有一个数字来匹配 \d+ In [8]: r = re.match(r"(.+)(\d+-\d+-\d+-\d+)", s) In [9]: r.groups() Out[9]: ('this is a number 23', '4-235-22-423') #加上?表示关掉贪婪模式,此时会从后面的\d+开始匹配,来适应前面的内容 In [10]: r = re.match(r"(.+?)(\d+-\d+-\d+-\d+)", s) In [11]: r.groups() Out[11]: ('this is a number ', '234-235-22-423')