首页 > 其他 > 详细

正则表达式

时间:2020-02-23 01:43:49      阅读:70      评论:0      收藏:0      [点我收藏+]

1.  正则表达式介绍

2. re 模块

3. 匹配单个字符

4. 匹配多个字符

5. 匹配边界

6. 匹配分组

7. re 模块的高级用法

8. 贪婪和非贪婪

9. 小练习

 

 

1.  正则表达式介绍

正则表达式(英语:Regular Expression,在代码中常简写为 regex、regexp 或 RE),是计算机科学的一个概念,Regular Expression 即“描述某种规则的表达式”之意。

正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。

在很多文本编辑器里,正则表达式通常被用来检索、替换那些匹配某个模式的文本。

 

2. re 模块

在 Python 中需要通过正则表达式对字符串进行匹配的时候,可以使用一个模块,名字为 re。

基本用法

import re

# 使用match方法进行匹配操作
result = re.match(正则表达式, 要匹配的字符串)

# 如果上一步匹配到数据的话,可以使用group方法来提取数据
result.group()
  • match():是用来进行正则匹配检查的方法,若字符串匹配正则表达式,则 match 方法返回匹配对象(Match Object),否则返回None。

  • group():匹配对象 Macth Object 具有 group 方法,用来返回字符串的匹配部分。

示例:

1 >>> import re
2 >>> result = re.match("hello", "hello world")  # match() 能够匹配出以xxx开头的字符串
3 >>> result.group()
4 hello

原生字符串

  • Python 中字符串前面加上 r 表示原生字符串。

  • 与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"\",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。

  • Python 里的原生字符串很好地解决了这个问题,有了原始字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。

 1 >>> s = "\\a"
 2 >>> s
 3 \\a
 4 >>> print(s)
 5 \a
 6 >>>
 7 >>> ret = re.match("\\\\a", "\\a").group()  # 转义
 8 >>> ret
 9 \\a
10 >>> print(ret)
11 \a
12 >>> ret = re.match(r"\\a", "\\a").group()  # 原生字符串
13 >>> ret
14 \\a
15 >>> print(ret)
16 \a

 

3. 匹配单个字符

正则表达式的单字符匹配如下:

字符功能
. 匹配任意1个字符(除了\n)
[ ] 匹配[ ]中列举的字符;[^]中的^代表非
\d 匹配数字,即0-9
\D 匹配非数字,即不是数字
\s 匹配空白,即 空格,tab键
\S 匹配非空白
\w 匹配单词字符,即a-z、A-Z、0-9、_
\W 匹配非单词字符

示例:

 1 >>> import re
 2 >>> result = re.match("嫦娥\d号", "嫦娥1号")
 3 >>> result.group()
 4 嫦娥1号
 5 >>> result = re.match("嫦娥\d号", "嫦娥2号")
 6 >>> result.group()
 7 嫦娥2号
 8 >>> result = re.match("[a-zA-Z]", "Hello World")
 9 >>> result.group()
10 H

 

4. 匹配多个字符

匹配多个字符的相关格式:

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

示例1:*

匹配出,一个字符串第一个字母为大小字符,后面都是小写字母并且这些小写字母可有可无:

1 >>> re.match("[A-Z][a-z]*", "Faaa").group()
2 Faaa
3 >>> re.match("[A-Z][a-z]*", "F").group()
4 F

示例2:+

匹配出,变量命名是否有效:

1 >>> re.match("[a-zA-Z_]+[\w]*", "Name").group()
2 Name
3 >>> re.match("[a-zA-Z_]+[\w]*", "_Name").group()
4 _Name
5 >>> re.match("[a-zA-Z_]+[\w]*", "1_Name").group()
6 Traceback (most recent call last):
7   File "<stdin>", line 1, in <module>
8 AttributeError: NoneType object has no attribute group

示例3:?

匹配出,0到99之间的数字:

1 >>> re.match("[1-9]?[0-9]", "09").group()
2 0
3 >>> re.match("[1-9]?\d", "12").group()
4 12
5 >>> re.match("[1-9]?[0-9]", "100").group()
6 10

示例4:{m}

匹配出,8到20位的密码,可以是大小写英文字母、数字、下划线:

 1 >>> re.match("[\w]{8,20}", "1234567").group()
 2 Traceback (most recent call last):
 3   File "<stdin>", line 1, in <module>
 4 AttributeError: NoneType object has no attribute group
 5 >>> re.match("[\w]{8,20}", "1234567a").group()
 6 1234567a
 7 >>> re.match("[\w]{8,20}", "1234567aA_").group()
 8 1234567aA_
 9 >>> re.match("[\w]{8,20}", "1234567aA_000000000000000000").group()
10 1234567aA_0000000000

 

5. 匹配边界

字符功能
^ 匹配字符串开头
$ 匹配字符串结尾
\b 匹配一个单词的边界
\B 匹配非单词边界

示例1:$

匹配 163.com 的邮箱地址:

 1 >>> re.match("[\w]{4,20}@163\.com", "123aa_A@163.com").group()
 2 123aa_A@163.com
 3 >>> re.match("[\w]{4,20}@163\.com", "123aa_A@163.com_sada").group()
 4 123aa_A@163.com
 5 >>> re.match("[\w]{4,20}@163\.com$", "123aa_A@163.com_sada").group()
 6 Traceback (most recent call last):
 7   File "<stdin>", line 1, in <module>
 8 AttributeError: NoneType object has no attribute group
 9 >>> re.match("[\w]{4,20}@163\.com$", "123aa_A@163.com").group()
10 123aa_A@163.com

示例2: \b

注意,\b 在正则中表示单词间隔,但 \b 在字符串里本身是个转义,代表退格。因此需要加 r 表示 正则中的单词间隔。

而相比于\b, 像 \w、\d 只有一种解释,并没有对应的转义字符,所以不加 r,也不会出错。

1 >>> re.match(r".*\bhello\b", "soda hello ver").group()
2 soda hello
3 >>> re.match(r".*\bhello\b", "soda hellover").group()
4 Traceback (most recent call last):
5   File "<stdin>", line 1, in <module>
6 AttributeError: NoneType object has no attribute group
7 >>> re.match(r".*\bhello\b", "hello ver").group()
8 hello

示例3:\B

 1 >>> re.match(r".*\Bhello\B", "hellover").group()
 2 Traceback (most recent call last):
 3   File "<stdin>", line 1, in <module>
 4 AttributeError: NoneType object has no attribute group
 5 >>> re.match(r".*\Bhello\B", "_hellover").group()
 6 _hello
 7 >>> re.match(r".*\Bhello\B", "hello").group()
 8 Traceback (most recent call last):
 9   File "<stdin>", line 1, in <module>
10 AttributeError: NoneType object has no attribute group

 

6. 匹配分组

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

示例1:|

匹配出0-100之间的数字:

 1 >>> re.match("[1-9]?\d", "08").group()
 2 0
 3 >>> re.match("[1-9]?\d$", "08").group()
 4 Traceback (most recent call last):
 5   File "<stdin>", line 1, in <module>
 6 AttributeError: NoneType object has no attribute group
 7 >>> re.match("[1-9]?\d$|100|0", "8").group()  # 满足3组规则中的一组即可
 8 8
 9 >>> re.match("[1-9]?\d$|100", "78").group()
10 78
11 >>> re.match("[1-9]?\d$|100", "100").group()
12 100

示例2:( )

匹配出163、126、qq邮箱之间的数字:

1 >>> re.match("(\w+)@(163|126|qq)\.com$", "123a@qq.com").group()
2 123a@qq.com
3 >>> re.match("(\w+)@(163|126|qq)\.com$", "123a@163.com").group()
4 123a@163.com
5 >>> re.match("(\w+)@(163|126|qq)\.com$", "123a@163.coma").group()
6 Traceback (most recent call last):
7   File "<stdin>", line 1, in <module>
8 AttributeError: NoneType object has no attribute group

取出分组部分:

1 >>> ret = re.match("([^-]*)-(\d+)", "010-1321331")
2 >>> ret.group()
3 010-1321331
4 >>> ret.group(1)  # 取出第一个分组
5 010
6 >>> ret.group(2)  # 取出第二个分组
7 1321331

示例3:\number

匹配出<html><h1>www.itcast.cn</h1></html>:

1 >>> re.match(r"<(\w*)><(\w*)>.*</\2></\1>", "<html><h1>www.itcast.cn</h1></html>").group()
2 <html><h1>www.itcast.cn</h1></html>

示例4:(?P<name>) (?P=name)

匹配出<html><h1>www.itcast.cn</h1></html>:

1 >>> re.match(r"<(?P<key1>\w*)><(?P<key2>\w*)>.*</(?P=key2)></(?P=key1)>", "<html><h1>www.itcast.cn</h1></html>").group()
2 <html><h1>www.itcast.cn</h1></html>

技术分享图片

 

7. re 模块的高级用法

  • search:匹配第一处符合规则的部分。
  • findall:匹配所有符合规则的部分,并组成列表返回。
  • sub:将匹配到的数据进行替换。
  • split:根据匹配进行切割字符串,并返回一个列表。

示例:

1 >>> re.search(r"\d+","预习次数为:2,复习次数为:6").group()  # search
2 2
3 >>> re.findall(r"\d+","预习次数为:2,复习次数为:6")  # findall
4 [2, 6]
5 >>> re.sub("\d+", "998", "python = 997")  # sub
6 python = 998
7 >>> re.split(":| ", "info:xiaoZhang 22 shandong")  # split,分隔符为冒号或空格
8 [info, xiaoZhang, 22, shandong]

sub 的第二种用法,传递函数作为参数:

1 import re
2 
3 def add_one(ret):
4     str_num = ret.group()
5     return str(int(str_num)+1)
6     
7 ret = re.sub("\d+", add_one, "python = 997")
8 print(ret)  # python = 998

 练习题:从下面的字符串中取出文本

<div>
        <p>岗位职责:</p>
<p>完成推荐算法、数据统计、接口、后台等服务器端相关工作</p>
<p><br></p>
<p>必备要求:</p>
<p>良好的自我驱动力和职业素养,工作积极主动、结果导向</p>
<p>&nbsp;<br></p>
<p>技术要求:</p>
<p>1、一年以上 Python 开发经验,掌握面向对象分析和设计,了解设计模式</p>
<p>2、掌握HTTP协议,熟悉MVC、MVVM等概念以及相关WEB开发框架</p>
<p>3、掌握关系数据库开发设计,掌握 SQL,熟练使用 MySQL/PostgreSQL 中的一种<br></p>
<p>4、掌握NoSQL、MQ,熟练使用对应技术解决方案</p>
<p>5、熟悉 Javascript/CSS/HTML5,JQuery、React、Vue.js</p>
<p>&nbsp;<br></p>
<p>加分项:</p>
<p>大数据,数理统计,机器学习,sklearn,高性能,大并发。</p>

        </div>
1 # 方法一:精确匹配
2 re.sub("</?\w*>", "", raw_str)
3         
4 # 方法二:使用非贪婪模式        
5 re.sub("<.+?>", "", raw_str)

 

8. 贪婪和非贪婪

Python 中正则表达式的数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),当它在从左到右的顺序求值时,总是尝试匹配尽可能多的字符。非贪婪则相反,总是尝试匹配尽可能少的字符。

在 "*"、"?"、"+"、"{m,n}" 后面加上?,可使贪婪变成非贪婪。

示例1:

1 >>> re.match(".+(\d+-\d+-\d+-\d+)", s).group(1)
2 4-235-22-423
3 >>> re.match(".+?(\d+-\d+-\d+-\d+)", s).group(1)
4 234-235-22-423

在上面的例子中,“.+”会从字符串的启始处抓取满足模式的最长字符,其中包括我们想得到的第一个整型字段的中的大部分,“\d+”只需一位字符就可以匹配,所以它匹配了数字“4”,而“.+”则匹配了从字符串起始到这个第一位数字4之前的所有字符。

因此解决方式为使用非贪婪操作符“?”,要求正则匹配的越少越好。

示例2:

1 >>> re.match("aa(\d+)", "aa1232ddd").group(1)
2 1232
3 >>> re.match("aa(\d+?)", "aa1232ddd").group(1)
4 1
5 >>> re.match("aa(\d+)ddd", "aa1232ddd").group(1)
6 1232
7 >>> re.match("aa(\d+?)ddd", "aa1232ddd").group(1)
8 1232

 

9. 小练习

1. 匹配网址

有一批网址:

http://www.interoem.com/messageinfo.asp?id=35
http://3995503.com/class/class09/news_show.asp?id=14
http://lib.wzmc.edu.cn/news/onews.asp?id=769
http://www.zy-ls.com/alfx.asp?newsid=377&id=6
http://www.fincm.com/newslist.asp?id=415

需要正则后为:

http://www.interoem.com/
http://3995503.com/
http://lib.wzmc.edu.cn/
http://www.zy-ls.com/
http://www.fincm.com/

答:

1 # 方法一
2 re.match(r"http://.*?/", s).group()
3 
4 # 方法二:使用替换,仅返回需要的部分
5 re.sub(r"(http://.*?/).*", lambda x: x.group(1), s)

2. 找出单词

有一句英文“hello world ha ha”,查找其中所有的单词:

1 >>> s = "hello world ha ha"
2 >>> re.split(" ", s)  # 方法一
3 [hello, world, ha, ha]
4 >>> re.findall("\w+", s)  # 方法二
5 [hello, world, ha, ha]

 

正则表达式

原文:https://www.cnblogs.com/juno3550/p/12345857.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!