note

正则表达式

正则表达式通用的学习地址:这里

python里面re库的使用:这里

这里写的都是正则表达式比较通用的,其它语言应该也没有问题

在pycharm中,写了一个正则表达式,可以把鼠标放在正则表达式上,按下Alt+Enter,然后可以在RexExp写上正则表达式的例子,看是否成功匹配,可以写很多,后面可以再进来查看示例的。

一、限定符|元字符

重要:==正则表达式里不要加多余为了美观或是习惯的 空格==

常用元字符 常用限定符
. 匹配 除了换行符\n以外的任意字符 * 重复零次或更多次
\w 匹配字母或数字或下划线或汉字(其它符号(好比!@#等)不行) + 重复一次或更多次
\s 匹配任意的空白符(即空格,tab键) ? 重复零次或一次
\d 匹配数字(后面不跟常用限定符,\d就代表匹配一个数字,其它同理) {n} 重复n次
\b 匹配单词的开始或结束 (用的比较少,一般用下面这个) {n,} 重复n次或更多次
^ & 匹配字符串的 ==开始== ==结束== {n,m} 重复n到m次
\u4e00-\u9fa5 这是utf-8中,中文编码的范围,代表所有中文汉字
所以使用时记得加==[]==,代表一个中文汉字,即[\u4e00-\u9fa5]
{n,m}这里面的逗号后不能跟空格

简单示例:

二、Python中使用

python中的简单使用:正则表达式(Regular Expression):python菜鸟教程里有

2.1 [ ] [\^ ] 的字符选择

这不仅仅局限于python,其它语言的正则应该也是可以的

除了以上写法,还有一种:

import  re
pattern = re.compile(r"正则表达式")      
pattern.match("匹配的内容")[0]         

Tips:

2.2 match

​ match自动的默认是匹配开头所以开头的^可加可不加(所以开头都匹配不上的话是会直接算失败的),但是它不管结尾的,如下:

match、search以及findall的区别

​ match这一系列,在其它语言基本也是通用的,其它的可能是python的re库比较独有的,可能其它语言有,也可能没有。

示例:

strings = "这是一个见得'美元债务'的测试,比如'新币债务'或者别的什么,'你好债务'吧"
word = r"[\u4e00-\u9fa5]{2}债务"      # 前面是代表汉字
re_out = re.search(word, strings)    
re_out = re.findall(word, strings)     

解读:

2.3 sub 字符串替换

下面的正则表达式大多加了一对==``==,不是很方便去看的话,复制到别的编辑器里看。

re.sub(r”\d”, “998”, “python!=996,c++=1024”) # 将匹配到的字符串全部替换,然后返回替换后的值

sub示例:用正则表达式去掉一些不要的字符(==去掉乱码==),类似于replace:

sub的第二个参数还可以放函数调用 (这好像就是Python独有)

import re
def my_add(temp):
    "temp:传的是一个正则匹配的结果"
    strNum = temp.group()
    new_num = int(strNum) + 1
    return str(new_num)

strings = "python = 998, c++ = 1024"
# ret = re.sub(r"\d+", "1001", strings)  # 这就是把所有匹配到的数字都换成1001,
ret = re.sub(r"\d+", my_add, strings)  # 这就是把每个数字+1而已

分析:匹配到了几次,就回去调用my_add函数几次,一次就处理一个结果。

2.4 split 切割字符串

split:根据匹配进行切割字符串,并==返回一个列表==:

按照空格或冒号切割:ret = re.split(r”: ”, “info:xiaonghao 33 hello”)
注意,解读正则表达式 r”: ” 其中|是分枝条件或,左边是冒号,右边有一个空格

三、其它

这里面的大抵都是正则表达式通用的。

3.1 分枝条件

​ 格式:一个正则表达式 另一个正则表达式 # 从左往右测试每个条件,满足其一就不再管其他条件(注意|两边不要有空格)

例子:如果是想匹配 123abc@163.com 或者 bbbsa@qq.com 这两种邮箱格式,那么

ret = re.match(r"[0-9A-z_]{4,20}@(163|qq)\.com", "songhui_cc@163.com")

​ 注意:写法是(163|qq)必须用括号括起来,不然满足左边的条件,后面的.com就没了(再次注意不能有空格),然后因为.是特殊字符,所有还必须转义一下。

3.2 分组

在正则中是将一个括号( )中的字符作为一组,分组除了在上面的分枝条件中用到,还有一些特殊用法:

3.3 贪婪与懒惰

懒惰限定符就是在“常用限定符”后面加个==?==的组合, 代表重复的次数尽可能的少

例:aabab
用a.*b    匹配最长的以a开始,以b结束的字符串,,所以结果会是aabab;称为贪婪匹配
用a.*?b  匹配最短的,以a开始,以b结束的字符串,所以结果是 aab 和 ab

再来:+? 重复1次或更多次,但尽可能少重复 {n,}? 重复n次以上,但尽可能少重复 # 其它的类似

3.4 负向零宽断言

更多的还是看网页教程吧

零宽度负预测先行断言(?!exp),断言此位置的后面不能匹配表达式exp。
例如:\d{3}(?!\d)匹配三位数字,而且这三位数字的后面不能是数字;\b((?!abc)\w)+\b匹配不包含连续字符串abc的单词。

同理,我们可以用(?<!exp),零宽度负回顾后发断言来断言此位置的前面不能匹配表达式exp
例如:(?<![a-z])\d{7}匹配前面不是小写字母的七位数字。

3.5 手机号匹配示例

例子:从一段文字中提取国内手机号码

​ 国内2017年底三大运营商现有号码开头[130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 145, 147, 150, 151, 152, 153, 155, 156, 157, 158, 159, 176, 177, 178, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189]

def main3():
    str = """重要的事情说8140123456789遍,我的手机号是13512346789这个靓号,不是15600998765,也是110或119,王大锤的手机号才是15600998765。
    是的14812345678是的,1512345687875"""
    pattern = re.compile(r"(?<!\d)(1[3 8]\d{9}|14[5 7]\d{8}|15[0-3 5-9]\d{8}|17[6 7 8]\d{8})(?!\d)")     
  #注意上面这个表达式,把中间的分枝条件用一个括号括起来,再再在前面用前瞻和回顾
    result = pattern.findall(str)
    print(result)