什么是正则表达式?
简单来说,正则表达式是一些用来匹配和处理文本的字符串。正则表达式通常被用来 检索、分割、替换那些匹配某个模式的文本。比如,我们想找出一个网页中的所有电子邮件,其他的信息需要过滤掉,此时,我们可以观察电子邮件的格式,然后写一个正则表达式来表示所有的电子邮件,随后,我们可以利用该正则表达式从网页中提取出所有满足该规则的字符串出来。
利用正则表达式还可以做很多事情,其主要用于字符串的匹配。在实际项目中,我们需要找到某一类符合某种格式的信息,此时我们可以观察这些数据的规律,然后将这些数据的格式规律用正则表达式描述出来,最后利用正则表达式函数进行相应的处理即可。
在Python中,一般我们会使用re
模块实现Python正则表达式的功能。
正则表达式可以利用这个工具进行测试:https://tool.oschina.net/regex/。
正则表达式也是一个字符串,一般称之为模式串,模式串一般由原子、元字符和修饰符组成。下面,我们来分别学习一下正则表达式的构成部分及其他基础知识。
原子是正则表达式中最基本的组成单位,每个正则表达式中至少要包含一个原子,常见的原子有以下几类:
下面,我们分别详细进行了解一下。
我们可以使用一些普通字符,比如数字、大小写字母、下划线等都可以作为原子使用。例如下面这个例子:
import re
pattern = "yue"
string = "http://yum.iqianyue.com"
result = re.search(pattern, string)
print(result)
# 运行结果:
<_sre.SRE_Match object; span=(16, 19), match='yue'>
上面我们设置了一个正则表达式pattern,并且定义了一个字符串string,然后使用re模块里的search()函数,从字符串string中去匹配对应的正则表达式,若能够匹配,则将匹配结果返回给变量result并打印出来。
任何一个符号都可以作为原子使用,但如果这个符号在正则表达式中有一些特殊意义,我们就必须使用转义字符“\”取消它的特殊意义,将其变成一个普通的原子。例如,所有标点符号以及一些其他符号(双引号“””、单引号“’”、“*”、“+”、“.”等),如果当原子就必须像\”
、\’
、\+
和\.
这样使用。如下示例:
import re
pattern = '\+'
string = "a+b=c"
result = re.search(pattern, string)
print(result)
# 运行结果:
<_sre.SRE_Match object; span=(1, 2), match='+'>
元字符的使用见第二部分。
所谓的非打印字符,指的是一些在字符串中用于格式控制的符号,比如换行符等,常用的非打印字符如下表:
符号 | 含义 | 等价 |
---|---|---|
\cx | 匹配由x指明的控制字符 | |
\f | 匹配一个换页符 | 等价于 \x0c 和 \cL |
\n | 匹配一个换行符 | 等价于 \x0a 和 \cJ |
\r | 匹配一个回车符 | 等价于 \x0d 和 \cM |
\t | 匹配一个制表符 | 等价于 \x09 和 \cI |
\v | 垂直制表 |
下面例子中在目标字符串中添加一个换行符,则代码及运行结果如下:
import re
pattern = "\n"
string = '''http://yum.iqianyue.com
http://baidu.com'''
result2 = re.search(pattern, string)
print(result2)
# 运行结果:
<_sre.SRE_Match object; span=(23, 24), match='\n'>
可以看到,程序中的字符串变量string包含一个多行数据,这个数据里面包含了对应的换行符,因此能够匹配成功。但如果string字符串中没有换行符,那么结果将输出None
,即没有匹配结果。
通用字符,即一个原子可以匹配一类字符,在实际操作中会经常遇到这类原子。常见的通用字符及其含义如下表所示:
符号 | 含义 |
---|---|
\w | 匹配任意一个字母、数字或下划线 |
\W | 匹配除字母、数字和下划线以外的任意一个字符 |
\d | 匹配任意一个十进制数 |
\D | 匹配除十进制数以外的任意一个其他字符 |
\s | 匹配任意一个空白字符 |
\S | 匹配除空白字符以外的任意一个其他字符 |
\A | 匹配字符串开头 |
\b | 匹配单词开头 |
\B | 匹配非单词的边界 |
例如下面示例:
import re
pattern = "\w\dpython\w"
string = "abcdfphp345python_pyspider"
result = re.search(pattern, string)
print(result)
# 运行结果:
<_sre.SRE_Match object; span=(9, 18), match='45python_'>
上面代码中我们使用pattern正则表达式对string字符串进行匹配,字符python后是一个字母、数字或下划线,字符前一位是一个任意的十进制数,再前一位是一个字母、数字或下划线,经运行代码,匹配成功后返回了字符串"45python_"。
使用原子表,可以定义一组地位平等的原子,然后匹配的时候会取该原子表中的任意一个原子进行匹配。在Python中,原子表由[]
表示。比如,我们定义了正则表达式[hijk]py
,对应的源字符串是“ipython”,若此时用re.search()函数进行匹配,就可以匹配出结果“ipy”,因为原子表[hijk]
中定义的四个原子地位平等,此时只要py前的字母是其中之一就可以匹配成功。
类似地,[^]
代表的是除了中括号里面的原子均可以匹配,比如“[^hijk]
”能匹配spy
,却不能匹配ipy
。如下示例:
import re
pattern1 = "\w\dpython[xyz]\w"
pattern2 = "\w\dpython[^xyz]\w"
pattern3 = "\w\dpython[xyz]\W"
string = "abcdfphp345pythony_py"
result1 = re.search(pattern1, string)
result2 = re.search(pattern2, string)
result3 = re.search(pattern3, string)
print(result1)
print(result2)
print(result3)
# 运行结果:
<_sre.SRE_Match object; span=(9, 19), match='45pythony_'>
None
None
所谓元字符,就是正则表达式中具有一些特殊含义的字符,比如重复N次前面的字符等。常用的一些元字符如下:
符号 | 含义 |
---|---|
. |
匹配除换行符以外的任意字符 |
^ |
匹配字符串的开始位置 |
$ |
匹配字符串的结束位置 |
* |
匹配0次、1次或多次前面的原子 |
? |
匹配0次或1次前面的原子 |
+ |
匹配1次或多次前面的原子 |
{n} |
前面的原子恰好出现n次 |
{n,} |
前面的原子至少出现n次 |
{n,m} |
前面的原子至少出现n次,至多出现m次 |
| |
模式选择符 |
() |
模式单元符 |
具体来说,元字符可以分为:任意匹配元字符、边界限制元字符、限定符、模式选择符、模式单位符等。
任意匹配元字符.
可以匹配一个除换行符以外的任意字符。比如,我们可以使用正则表达式.python...
匹配一个“python”字符前面有1位,后面有3位格式的字符串,而这前面和后面的字符都是除换行符以外的任意字符。如下示例:
import re
pattern = ".python..."
string = "abcdfphp345pythony_py"
result = re.search(pattern, string)
print(result)
# 运行结果:
<_sre.SRE_Match object; span=(10, 20