正则表达式基本概念

一、 正则表达式概述
    1. 作用:
     1. 数据抓取,数据的清理 : 在网上抓取图片,清除网站中不雅的评论
2. 数据验证,比如验证邮箱的合法性,手机号码的合法性 ,11位数字


    2. 特点:通用性,跨语言
    主流语言都有正则表达式,而且表达式的规则都几乎相同的

二、 re模块
   提示: 命令行: ctrl+e :到命令行的尾部
                    ctrl+A: 到命令行的头部
1. re模块的使用过程
    a>import re
  ret=re.match("itcast","itcast.cn")
  ret
b> 匹配成功没
在命令行输入:ret
   为空: 匹配失败
   不为空: 匹配成功
 
c> 查看结果
       ret.group()

2. 小结 
   1. re.match("正则表达式","要匹配的内容")
   2. re.match ()是匹配以xxx开头的字符串


三、 匹配单个字符

        

字符 功能
. 匹配任意1个字符(除了\n)
[ ] 匹配[ ]中列举的字符
\d 匹配数字,即0-9
\D 匹配非数字,即不是数字
\s 匹配空白,即 空格,tab键
\S 匹配非空白
\w 匹配单词字符,即a-z、A-Z、0-9、_
\W 匹配非单词字符
1. '.' : 表示匹配任意一个字符,除\n(换行)以外  
  问题: 看电影 输入电影名称: "速度与*情"
   re.match("速度与.情","速度与基情")
   re.match("速度与.情","速度与\n情")

2.[] : 匹配[ ]中列举的字符
  问题: 看电影 选择电影名称: "速度与激情9"  1-9部都可以
re.match("速度与激情[123456789]","速度与激情1")
re.match("速度与激情[1-9]","速度与激情8")
re.match("速度与激情[1-35-9]","速度与激情5")   : 除4以外的所有字符

3. \d: 表示任意一个数字 ,0-9 中的数字
re.match("速度与激情\d","速度与激情9")

4. \D: 不是数字的任意一个字符
re.match("速度与激情\D","速度与激情*")

5. \s : 匹配空格或者tab空格
re.match("速度与激情\s","速度与激情         ")
re.match("速度与激情\s","速度与激情#")

6. \S : 除了空格tab键的空格以外的所有字符
re.match("速度与激情\S","速度与激情u")
re.match("速度与激情\S","速度与激情    ")

7. \w : 匹配单词字符: 0-9,a-z,A-Z,_
    python2:单词字符不支持中文,python3支持中文,命名单词或者变量不建议用中文
re.match("\w","9")
re.match("\w","A")
re.match("\w","*")

       8. \W : 匹配单词字符以外的所有字符
re.match("\W","9")
re.match("\W","A")
re.match("\W","*")
    

四、 匹配多个字符

字符 功能
* 匹配前一个字符出现0次或者无限次,即可有可无
+ 匹配前一个字符出现1次或者无限次,即至少有1次
? 匹配前一个字符出现1次或者0次,即要么有1次,要么没有
{m} 匹配前一个字符出现m次
{m,n} 匹配前一个字符出现从m到n次

1. {m} : 匹配前一个字符出现m次
  问题:匹配手机号码, 11位数字  
  re.match("1\d{10}","13656789857")
  re.match("1\d{10}","1365678985")

2. {m,n}: 匹配前一个字符出现m到n次  
  问题: 匹配广东电话号码的合法性  020-56745675 ,0755-12345678,0756-1234567
   re.match("\d{3}-\d{8}","020-56745795")
   re.match("\d{3,4}-\d{8}","0755-56745795")
   re.match("\d{3,4}-\d{7,8}","0756-5674595")

3. ? : 前一个字符出现1次或者0次
问题: 匹配广东电话号码的合法性  02056745675 ,0755-12345678,07561234567
re.match("\d{3,4}-?\d{7,8}","07565674595")
re.match("\d{3,4}-?\d{7,8}","0756-5674595")
    
4. * : 匹配前一个字出现0次或者多次
问题: 把一个文本的内容全部匹配出来 
content="""adslfjaldjgljagga\nasdiwerierydfgjr\n;sdfgrwjtrjg""" 
re.match(".*",content,re.S)
re.match("a*","")
  注意: 
     1.  "." 不能匹配换行 \n
2. re.S 表示多行匹配

5. + :匹配前一个字符出现1次或者无限次,即至少有1次 
问题:空字符串匹配
  re.match("a+","")
  re.match("a+","aaaaaaaa")


五、匹配开头与结尾
1. ^ : 匹配以xxx开头的字符串
  re.match("^itcast","itcast.cn")
  re.match("itcast","itcast.cn") :match默认就是以itcast开头
  re.match("^itcast","uitcast.cn")
  re.match("itcast","uitcast.cn")

2. $ :匹配以xxx结尾的字符串
   问题: 11位手机号码匹配
   re.match("1\d{10}$","13654678906")
   re.match("1\d{10}$","13654678906897")

六、案例:
  1. 案例1: 判断变量名是否合法    
  names = ["age1", "1age", "AG0_", "_9age", "age_", "a9_G2#", "a#ffsd"]
  需求(规则): 变量名合法: 字符由a-z,A-Z,0-9,_ 组成,但是首字符不能是数字  
ret=re.match("[a-zA-Z_]\w*$",name)


参考代码:

import re

def main():
"""需求(规则): 变量名合法: 字符由a-z,A-Z,0-9,_ 组成,但是首字符不能是数字"""
names = ["age1", "1age", "AG0_", "_9age", "age_", "a9_G2#", "a#ffsd"]


# 迭代可迭代对象
for name in names:
ret=re.match("[a-zA-Z_]\w*$",name)
if ret:
print("变量名%s合法,匹配到的内容%s" %(name,ret.group()))
else:
print("变量名%s不合法"%name)

if __name__ == '__main__':
main()
 
   
  2. 案例2: 
     匹配出163的邮箱地址,且@符号之前有4到20位单词字符,例如hello@163.com
  email_list = ["lijun@163.com", "wang2_@qq.com", "lining@163.cn", "wang@163.com.cn","cheny@163ccom"]
ret = re.match("\w{4,20}@163\.com$",email)
  
 
参考代码:
import re

def main():
"""匹配出163的邮箱地址,且@符号之前有4到20位单词字符,例如hello@163.com"""
email_list = ["lijun@163.com", "wang2_@qq.com", "lining@163.cn", "wang@163.com.cn", "cheny@163ccom"]


# 遍历列表
for email in email_list:
# . 在正则表达式中表示匹配任意一个字符,但是当前需要一个 ".",通过"\" 转义符 转回原生(原来、本来的意义,初始的意义)的意义
ret = re.match("\w{4,20}@163\.com$",email)
if ret:
print("邮箱%s合法的,匹配的内容是:%s" % (email, ret.group()))
else:
print("邮箱%s不合法" % email)
if __name__ == '__main__':
main()

   
七、匹配分组

字符 功能
| 匹配左右任意一个表达式
(ab) 将括号中字符作为一个分组
\num 引用分组num匹配到的字符串
(?P<name>) 分组起别名
(?P=name) 引用别名为name分组匹配到的字符串

1. | :匹配左右任意一个表达式
  问题: 同时匹配出 163和126邮箱的合法性(@符号之前有4到20位单词字符) 
  re.match("\w{4,20}@163\.com$|\w{4,20}@126\.com$","lijun@126.com")
  re.match("\w{4,20}@163\.com$|\w{4,20}@126\.com$","lijun@163.com")

2. (ab) : 分组
  
    问题1: 匹配多个邮箱地址
     1. re.match("\w{4,20}@(163|126|qq)\.com$","lijun@126.com")
问题2:想取出合法邮箱特定的值,比如取163,126或者邮箱的前缀
In [166]: ret=re.match("(\w{4,20})@(163|126|qq)\.com$","lijun@qq.com")

In [167]: ret.group()
Out[167]: 'lijun@qq.com'

In [168]: ret.group(0)
Out[168]: 'lijun@qq.com'

In [169]: ret.group(1)
Out[169]: 'lijun'

In [170]: ret.group(2)
Out[170]: 'qq'

 
3. \num : 引用分组num匹配到的字符串
  问题:需求(规则): html标签配对验证, 比如<h1>dsafagd</h1> ,标签必须配对
  re.match("<(\w+)>.*</\\1>","<h1>你好dsafagd</h1>")
  re.match("<(\w+)>.*</\\1>","<h1>你好dsafagd</h2>")
    
In [188]: print("\1") : "\1" : 转义成特殊的符号的,所以需要"\\1" ,转出原来的意义即反斜杠 \num
  

4. (?P<name>):分组起别名   
5. (?P=name) : 引用别名为name分组匹配到的字符串
  问题:问题4:需求:html标签配对验证, 比如<body><h1>dsafagd</h1></body>
    1. re.match("<(\w+)><(\w+)>.*</\\2></\\1>","<body><h1>你好dsafagd</h1></body>")
2. re.match("<(\w+)><(\w+)>.*</\\2></\\1>","<body><h1>你好dsafagd</h1></bod>")
3. re.match("<(?P<p1>\w+)><(?P<p2>\w+)>.*</(?P=p2)></(?P=p1)>","<body><h1>你好dsafagd</h1></body>")

   

八. re模块的高级用法
a>re.search() :查找,搜索, 当搜索到匹配的内容,则返回
问题:匹配微信公众号文章阅读的次数 :   "本文章阅读次数: 9998"
re.search("\d+","本文章阅读次数: 9998")
        
b>re.findall() : 找到所有匹配的数据,返回的是list
问题:找到本文的所有数字    "本文章阅读次数: 9998次,博客的阅读次数: 50"
ret=re.findall("\d+","本文章阅读次数: 9998次,博客的阅读次数: 50")
ret是列表,注意不要使用ret.group()
    
c> re.sub() : 替换操作
     语法:re.sub("正则表达式","替换的内容","查找的字符串或者文本")

问题:将匹配到的阅读次数加1    "本文章阅读次数: 9998次,博客的阅读次数: 50"

In [226]: def add(temp):
...:     strNum=temp.group()
...:     num=int(strNum)+1
...:     return str(num)
...: 
...: 


In [227]: ret=re.sub("\d+",add,"本文章阅读次数: 9998次,博客的阅读次数: 50")

In [228]: ret
Out[228]: '本文章阅读次数: 9999次,博客的阅读次数: 51'


d> split 根据匹配进行切割字符串,并返回一个列表
   语法:re.split("分隔符正则表达式","要分割的文本")
   问题: 分离字符串 "wang 18 广州 python" 
   In [230]: ret=re.split(" |:|-","wang 18-广州:python")

In [231]: ret
Out[231]: ['wang', '18', '广州', 'python']

In [232]: ret[0]
Out[232]: 'wang'


九、贪婪和非贪婪
Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;非贪婪则相反,总是尝试匹配尽可能少的字符。
在"*","?","+","{m,n}"后面加上?,使贪婪变成非贪婪。
  "*","?","+","{m,n}" : 特点,取字符的不确定性,存在贪婪与非贪婪,python默认是贪婪的,在"*","?","+","{m,n}"后面 加 ? ,把贪婪变为非贪婪
  
  非贪婪
  *: 0
  ?: 0
  +: 1
  {m,n} :m个
  
  re.search("https://.+?\.jpg",img)


十、r的作用
   Python中字符串前面加上 r 表示原生字符串
   问题:与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰
   re.match("<(\w+)><(\w+)>.*</\\2></\\1>","<body><h1>你好dsafagd</h1></bod>")
   ret=re.match(r"<(\w+)><(\w+)>.*</\2></\1>","<body><h1>你好dsafagd</h1><
    ...: /body>")
把转义符\变为原生的反斜杠

转载于:https://www.cnblogs.com/chenshichenyin/p/10689771.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值