Bootstrap

Python中的正则

1. 什么是正则?有什么用?

可以利用正则表达式简单、快速和高效的检索出我们需要查找的文字

正则表达式非常的强大,使用正则表达式关键的地方在于如何写出正确的【表达式语法】

2. 正则表达式中的特殊符号

2.1 *(星号)-重复匹配任意次

*表示匹配前面的字符任意次,包括0次

比如:你要从下面的文本中,选择逗号后面字符串内容,包括逗号本身,注意,这里的逗号是中文的逗号。

苹果,是绿色的
橙子,是橙色的
香蕉,是黄色的
乌鸦,是黑色的
猴子,

就可以这样写正则表达式:,.*

*紧跟在 .后面,表示 任意字符可以出现任意次,所以整个表达式的意思就是在逗号后面的所有字符,包括逗号

2.2 +(加号)-重复匹配多次

+表示匹配前面的子表达式一次或多次,不包括0次

比如:还是2.1 中的例子,你要从文本中,选择每行逗号后面的字符串内容,包括逗号本身。

但是添加一个条件,如果逗号后面没有内容,就不要选择。

就可以这样写正则表达式:,.+

2.3 {}(花括号)-匹配指定的次数

{}表示前面的字符匹配指定的次数

比如,下面的文本

红彤彤,绿油油,黑乎乎,绿油油油油

表达式:油{3,4}就表示匹配连续的 油 字 至少3次,至多4次

2.4 [](方括号)-匹配几个字符之一

[]表示要匹配某几种类型的字符

比如:[abc]可以匹配 a,b或者c里面的任意一个字符。等价于[a-c]

[a-c]中间的- 表示一个范围从 a 到 c。

如果你想匹配所有的小写字符,可以使用[a-z]

  • 注意:一些元字符在方括号内失去了魔法,变得和普通字符一样了

比如:[akm.]匹配a,k,m,.里面的任意一个字符

这里的.在括号里面不在表示匹配任意字符了,而就是表示匹配 . 这个字符

  • 如果在放括号中使用^ 表示非的意思

比如[^\d]表示选择非数字的字符

2.5 ()(括号)-组选择

括号称为正则表达式的 组选择,是从正则表达式匹配的内容里面扣去除其中的某些部分

例如:从下面的文本中,选择每行逗号前面的字符串,也包括逗号本身。

苹果,苹果是绿色的
橙子,橙子是橙色的
香蕉,香蕉是黄色的

我们就可以这样写正则表达式^.*,

但是,我们要求不要包括逗号呢?

当然不能直接写^.*

因为最后的逗号是特征所在,如果去掉它,就没法找逗号前面的字符了

但是把逗号放在正则表达式中,又会包含逗号

解决问题的方法就是使用组选择符:括号。

我们这样写 ^(.*),这样就可以实现我们的需求

2.6 ?(问号)-匹配0-1次

?表示匹配前面的子表达式0次或者1次

3. 贪婪模式和非贪婪模式

在正则表达式中,* + ?都是贪婪的,使用它们时,会尽可能多的匹配内容

我们要把下面的字符串中所有的html标签都提取出来

source = "<html><head><title>Title</title>"

我们想要得到这样的一个列表

['<html>','<head>','<title>','</title>']

很容易的想到使用正则表达式:<.*>

  • 在python中完整的写法:
source = "<html><head><title>Title</title>"
import re 
p = re.compile(r'<.*>')
print(p.findall(source))

但是运行结果是

["<html><head><title>Title</title>"]
  • 尽可能多的匹配内容,这就是贪婪模式

如果我们需要使用非贪婪模式,即:尽可能少的匹配我们的内容

我们需要在星号后面加上?,变成.*?就可以实现我们想要的结果

4. 对元字符的转义

反斜杠\在正则表达式中有多种用途。

比如,我们要在下面的文本中搜索所有点前面的字符串,也包含点本身

苹果.是绿色的
橙子.是橙色的
香蕉.是黄色的

我们马上会想到可以这样写正则表达式.*. 聪明的你会认识到这样写是不对的,

因为为什么第一个 . 就是匹配任意字符,第二个. 就是以. 结尾呢

这是我们就可以使用反斜杠\进行转义。

正确的正则表达式为:.*\.

匹配某种字符类型

反斜杠\后面接一些字符,表示匹配某种种类类型的一个字符。

  1. \d匹配0-9之间任意一个数字字符,等价于表达式[0-9]
  2. \D匹配任意一个不是0-9之间的数字字符,等价于表达式[^0-9]
  3. \s匹配任意一个空白字符,包括空格、tab、换行等等,等价于表达式[\t\n\r\f\v]
  4. \S匹配任意一个非空白字符,等价于表达式[^\t\n\r\f\v]
  5. \w匹配任意一个文字字符,包括大小写字母、数字、下划线,等价于表达式[a-zA-Z0-9]
  6. \W匹配任意一个非文字字符,等价于表达式[^a-zA-Z0-9]

反斜杠\也可以用在方括号里面,比如[\s,.]表示匹配:任何空白字符,或者逗号,或者点

5. 起始位置、结束位置和单行、多行模式

  1. ^表示匹配文本的起始位置

正则表达式可以设定【单行模式】和【多行模式】

如果是【单行模式】,表示匹配整个文本的开头位置

如果是【多行模式】,表示匹配文本每行的开头位置

  1. $表示匹配文本的结束位置

如果是【单行模式】,表示匹配整个文本的结束位置

如果是【多行模式】,表示匹配文本每行的结束位置

比如:下面的文本中,每行最前面的数字表示水果的编号,最后的数字表示价格

001-苹果价格-60
002-橙子价格-70
003-香蕉价格-80

如果我们要获取所有的水果编号,用这样的正则表达式 [^\d+]

如果我们要获取所有的水果价格,用这样的正则表达式[\d+$]

  • 在python中的写法
content = ```001-苹果价格-60
002-橙子价格-70
003-香蕉价格-80
```

import re
# re.M 表示开启多行模式  compile函数的第二个参数表示匹配的模式
p = re.compile(r'^\d+',re.M)
for one in p.findall(content):
    print(one)

6. 使用正则表达式切割字符串

字符串对象的split()方法只是用与非常简单的字符串分割情形,当你需要更加灵活的切割字符串的时候,就不好用了。

比如:我们需要从下面的字符串中提取武将的名字。

我们发现这些名字之间,有的是分号隔开,有的是逗号隔开,有的是空格隔开,而且分割符号周围还有不定数量的空格

names = '关羽; 张飞, 赵云,马超, 黄忠 李逵'

这时,最好使用功能正则表达式里面的split方法:

import re

names = '关羽; 张飞, 赵云,马超, 黄忠, 李逵'
namelist = re.split(r'[;,\s]*',names)
print(namelist)

正则表达式[;,\s]\s*指定了,分割符为分号、逗号、空格里面的任意一种均可,并且该符号周围可以有不定数量的空格

;