玩命加载中...
# Python中的正则表达式
4个小节,预计用时**20分钟**。
正则表达(Regular Expression,或简称RegEx)是编程语言中用来搜索文本中格式匹配的重要手段。比如说判断一个字符串是否包含合法的Email地址、找到文本中电话号码形式的字符出现的位置等等。
本教程将教会大家如何在Python中使用正则表达。
本教程基于**Python 3.7**。
原创者:**[我小宋](http://sofasofa.io/user_profile.php?id=1005970)** | 修改校对:SofaSofa TeamM |
----
### 0. 准备
Python3中有自带的正则表达模块`re`,和其他模块一样,我们只需要`import`即可加载。
```python
import re
```
下面的小例子,就是查找字符串中所有的`in`。通常我们在正则表达的格式前面加上`r`,比如下面的`r"in"`。
```python
string = "Taiwan is a province in China."
x = re.findall(r"in", string)
print(x)
```
['in', 'in', 'in']
### 1. 入门正则表达式
正则表达式本身也是用字符串表示,通常在引号前加上`r`。我们首先了解如何用字符来描述字符。
`\d`表示一个数字;
`\w`表示一个数字、一个字母或者一个下划线;
`\s`表示一个空格;
`?`表示任意0个或者一个字符;
`.`表示任意一个字符;
`*`表示任意一个字符串,甚至可以是空字符串;
`+`表示任意一个非空的字符串;
`[]`表示一个集合。
下面的例子中`r"i\w\w"`表示一个长度为3的字符串,第一个字符为`i`,第二三个字符是一个字母或者数字或者下划线。
所以我们得到的结果是`int`和`ing`。
```python
string = "I'm interested in buying the new BMW i3 car."
x = re.findall(r"i\w\w", string)
print(x)
```
['int', 'ing']
`r"i\d"`表示一个长度为2的字符,第一个字符为`i`,第二个字符是数字。
```python
string = "I'm interested in buying the new BMW i3 car."
x = re.findall(r"i\d", string)
print(x)
```
['i3']
`r"\w*i\w*"`表示包含字母`i`的子字符串。
```python
string = "I'm interested in buying the new BMW i3 car."
x = re.findall(r"\w*i\w*", string)
print(x)
```
['interested', 'in', 'buying', 'i3']
`r"\w*[abc]\w*"`表示包含字母`a`或者`b`或者`c`的子字符串。
```python
string = "I'm interested in buying the new BMW i3 car."
x = re.findall(r"\w*[abc]\w*", string)
print(x)
```
['buying', 'car']
### 2. [ ]集合的使用
上一个例子我们看到了集合符号`[ ]`的一个例子。其实集合还有更丰富的用法,例如:
`[125]`表示`1`或者`2`或者`5`;
`[3-7]`表示`3`到`7`的一个数字,也就是`3`、`4`、`5`、`6`、`7`;
`[0-9+]`表示`0`到`9`的一个数字或者`+`;
`[a-z]`表示`a`到`z`的一个小写字母;
`[a-zA-Z]`表示`a`到`z`的或者`A`到`Z`的一个大写字母;
`[^xyz]`表示除了`x`、`y`、`z`以外的任意一个字符;
`[]{n}`表示一个长度为n的子字符串,每个字符都来自集合;
`[]{n,m}`表示一个长度大于等于n小于等于m的子字符串,每个字符都来自集合。
`r"2[0-9]{3}"`表示以2开头的所有的四位数。下面的例子中,我们提取了句子中所有的年份。
```python
string = "克洛泽参加的4届世界杯中,他一共打入16球,其中2002世界杯5球,2006德国世界杯5球,2010南非世界杯4球,2014巴西世界杯2球。"
x = re.findall(r"2[0-9]{3}", string)
print(x)
```
['2002', '2006', '2010', '2014']
### 3. re中的常见方法
`re`中的常见用法有`re.search`、`re.match`、`re.findall`、`re.split`、`re.sub`。
#### 3.1 re.search
`re.search(pattern, string)`是搜索`string`中符合`pattern`的第一个字符串,返回一个`SRE_Match`对象。下面的例子中,我们搜索句子中第一个的年份;如果没有找到,则返回None。
```python
string = "克洛泽参加的4届世界杯中,他一共打入16球,其中2002世界杯5球,2006德国世界杯5球,2010南非世界杯4球,2014巴西世界杯2球。"
x = re.search(r"2[0-9]{3}", string)
print('第一个年份:', x.group())
print('在string的范围:', x.span())
print('开头的位置:', x.start())
print('结束的位置(不包含):', x.end())
```
第一个年份: 2002
在string的范围: (24, 28)
开头的位置: 24
结束的位置(不包含): 28
#### 3.2 re.match
`re.match(pattern, string)`是对`string`和`pattern`进行匹配,返回一个`SRE_Match`对象,如果匹配失败则返回None。`match`是`search`的特殊情况,`match`必须从`string`的第一个字符开始匹配,要求更严格。
```python
string = "克洛泽参加的4届世界杯中,他一共打入16球,其中2002世界杯5球,2006德国世界杯5球,2010南非世界杯4球,2014巴西世界杯2球。"
x = re.search(r"2[0-9]{3}", string)
if x:
print('re.search成功')
else:
print('re.search失败')
x = re.match(r"2[0-9]{3}", string)
if x:
print('re.match成功')
else:
print('re.match失败')
```
re.search成功
re.match失败
#### 3.3 re.findall
`re.findall(pattern, string)`是从`string`找到所有符合`pattern`的子字符串,返回一个list,如果没有找到则返回一个空的list。
```python
string = "克洛泽参加的4届世界杯中,他一共打入16球,其中2002世界杯5球,2006德国世界杯5球,2010南非世界杯4球,2014巴西世界杯2球。"
x = re.findall(r"2[0-9]{3}", string)
print(x)
```
['2002', '2006', '2010', '2014']
#### 3.4 re.split
`re.split(pattern, string)`是从`string`找到所有符合`pattern`的子字符串,并以这些子字符串为切割点,对原字符串进行分隔,返回得到一个list,每个元素是被分割的子字符串。
如果没有找到则返回一个只包含`string`的list。
```python
string = "克洛泽参加的4届世界杯中,他一共打入16球,其中2002世界杯5球,2006德国世界杯5球,2010南非世界杯4球,2014巴西世界杯2球。"
x = re.split(r"2[0-9]{3}", string)
print(x)
```
['克洛泽参加的4届世界杯中,他一共打入16球,其中', '世界杯5球,', '德国世界杯5球,', '南非世界杯4球,', '巴西世界杯2球。']
#### 3.5 re.sub
re.split(pattern, replace, string)是查找替换的功能,从`string`找到所有符合`pattern`的子字符串,并替换成`replace`。
```python
string = "克洛泽参加的4届世界杯中,他一共打入16球,其中2002世界杯5球,2006德国世界杯5球,2010南非世界杯4球,2014巴西世界杯2球。"
x = re.sub(r"2[0-9]{3}", "某某年", string)
print(x)
```
克洛泽参加的4届世界杯中,他一共打入16球,其中某某年世界杯5球,某某年德国世界杯5球,某某年南非世界杯4球,某某年巴西世界杯2球。
### 4. 练习:利用Python正则表达判断合法Email地址
```python
def IsValidEmail(email):
pattern = r"[a-zA-Z0-9_+\.-]+@\w+\.\w+"
if not re.match(pattern, email):
return False
return True
email1 = 'submit@sofasofa.io'
print('Is %s valid? %s\n'%(email1, IsValidEmail(email1)))
email2 = 'a?b@gmail'
print('Is %s valid? %s\n'%(email2, IsValidEmail(email2)))
email3 = '123@456@qq.com'
print('Is %s valid? %s\n'%(email3, IsValidEmail(email3)))
```
Is submit@sofasofa.io valid? True
Is a?b@gmail valid? False
Is 123@456@qq.com valid? False