其实是昨天 不过现在已经凌晨了,刚过12点所以我就写到12号。今天学正则表达式,我感觉难度是有的但是不至于说太难,学了一点没学完 。这里把学的内容提炼一下。做个记。
正则表达式
匹配任意字符(除了空格):’.’
匹配任意数字:‘\d’
匹配的字符的数量:{这里写次数},例如:
a{3}bc 那就对应aaabc
也可以写a{3-10}bc 那就对应aaaa…bc(这里面的a会有3到10个)
匹配的内容[这里面写内容],例如:
[0-9]or[a-z]or[abcdef]or[asd232sadfgh]
print(re.search('[01]\d\d|2[0-4]\d|25[0-5]','188'))
结果
<re.Match object; span=(0, 3), match='188'>
这个是匹配ip地址的其中一个,其中的内容解释如下:
因为最大的ip数字是255,所以不会超过255,所以内容就是这样:[01]表示第一位可以为1或者0,因为只要不超过2xx的数字随便选,然后\d\d就表示匹配后面两位数字,接下来‘|’这个符号表示或者,跟or的意思一样。然后就开始分析第一位是2的情况,因为不超过255,所以第一位是2,第二位就是0到4,第三位就随便了。最后一个是25【0-5】,意思很明白,就是250到255这几个数字,这就是表示匹配的数字用正则表达式来写
print(re.search('(([01]{0,1}\d{0,1}\d{0,1}|2[0-4]\d|25[0-5])\.){3}[01]{0,1}\d{0,1}\d{0,1}|2[0-4]\d|25[0-5]','200.200.200.200'))
结果
<re.Match object; span=(0, 14), match='200.200.200.20'>
这边要解释的就是‘{0,1} ’ 这个意思是重复,就是重复0次或者1次,举个例子:因为IP地址是0到255,那么这个数字有可能是三位数或者两位数或者一位数,所以如果想用三位数字的限定范围来限定他,必定要涉及到类似‘010,005’这样的数字,所以为了保证数字的合理性,就设置第一位数字的重复性,如果为0就代表什么也没有,如果为1,就代表存在,当然规范说法就是重复一次或者存在一次,那么后面的‘{}’就好理解了。还有这里面有个小括号,把‘.’给拒绝在门外了,这是因为不加这个,就不会表示前面的是一个整体,就会出现错误,因为你要先保证前面的数字的准确匹配,才能够进行这个点的匹配,当然最后运行出来的结果又bug,下面一段会进行解释。
print(re.search('(2[0-4]\d|[01]{0,1}\d{0,1}\d{0,1}|25[0-5])\.(2[0-4]\d|[01]{0,1}\d{0,1}\d{0,1}|25[0-5])\.(2[0-4]\d|[01]{0,1}\d{0,1}\d{0,1}|25[0-5])\.(2[0-4]\d|[01]{0,1}\d{0,1}\d{0,1}|25[0-5])','200.200.200.200'))
结果
<re.Match object; span=(0, 15), match='200.200.200.200'>
这边就承接上面的进行解释,解释之前先说明:这里我把重复三遍去掉了,因为我想检验一下其中的小细节,这些细节可以忽略。重点来了,因为前面出现的bug会导致结果中有个20而并非全是200,这是因为当正则表达式进行匹配的时候,在进行第一匹配时,[01]{0,1}\d{0,1}\d{0,1},200中的2在[0,1]{0,1}里面并不满足,但是在后面的\d{0,1}里面满足,然后200的中间的0就会自动去在最后面的\d{0,1}进行匹配,然后匹配直接结束,于是乎200里面的最后一个0则没有进行匹配,导致最后的结果是20,那么为了避免这种情况,所以就要把第二位的正则表达式放到最前面,也就是
[01]{0,1}\d{0,1}\d{0,1}|2[0-4]\d|25[0-5]).变成了
2[0-4]\d|[01]{0,1}\d{0,1}\d{0,1}|25[0-5]).
这样就能解决问题了
print(re.search(r'(1)(2)(3)\3\2','12332')
print(re.search(r'(huang)(hao)( )\3\2\1','huanghao haohuang'))#(匹配第n个分组的内容。)
结果
<re.Match object; span=(0, 5), match='12332'>
<re.Match object; span=(0, 18), match='huanghao haohuang'>
这两个放一起说,注释已经说得明白了,\数字表示匹配第n个分组的内容,也就是说‘()’这个表示一个分组,然后分先后顺序,第一个()就表示这个第一个,第二个()就表示第二个,()里面的内容就是表示匹配的内容,这个\数字也可以加在()和()的中间,比如(a)\1(b)\2
print(re.search(r'(a)\141','aa'))
结果
<re.Match object; span=(0, 2), match='aa'>
这个141是三位数,但凡\后面是三位数的,都是8进制的数字,需要转换成10进制,然后去看对应的ASCII码进行匹配,这8进制的数字可以先用16进制转换成8进制
print(re.findall(r'[a-z]','huanghao'))
结果
['h', 'u', 'a', 'n', 'g', 'h', 'a', 'o']
这个表示在a到z里面有的进行匹配,这个很简单,不多说了
print(re.findall(r'[\n]','huanghao\n'))
结果
['\n']
这个和上面的一样,\n属于换行符
print(re.findall(r'[^a-z]','H.huanghao\n'))
结果
['H', '.', '\n']
'^'要放在最前面,意思是匹配除了^后面的所有字符,若是放到最后就是已匹配前面的本身
print(re.search(r'abc{3}','abccc'))
结果
<re.Match object; span=(0, 5), match='abccc'>
这个也不解释了
s='<huang.>hao>'
print(re.search(r'<.+?>',s))
结果
<re.Match object; span=(0, 8), match='<huang.>'>
这个呢稍微解释一下,<是开始的<,然后这个点表示匹配任意字符,除了换行,然后是+,看图片就知道了,最后的>是s里面的>,那么重点是这个?,因为不加这个?,结果就是贪婪的匹配,就是所有的全部找到,加了这个?就表示停止贪婪匹配,点到为止