作者:billy
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处
什么是正则表达式
正则表达式(Regular Expression),常简写为 regex 或者 RE,又称为规则表达式。它不是某个编程语言所特有的,而是计算机科学的一个概念,通常被用来检索个替换符合某些规则的文本。目前,正则表达式已经在各种计算机语言(如 Java、C++ 和 Python 等)中得到了广泛的应用和发展。
正则表达式语法
-
行定位符:用来描述字符串的边界,‘^’ 表示行的开始,’$’ 表示行的结尾;
-
元字符:
代码 | 说明 |
---|---|
. | 匹配除换行符以外的任意字符 |
\w | 匹配字母或数字或下划线或汉字 |
\s | 匹配任意的空白符 |
\d | 匹配数字 |
\b | 匹配单词的开始或结束 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结束 |
- 重复:
限定符 | 说明 | 举例 |
---|---|---|
? | 匹配前面的字符零次或一次 | colou?r,该表达式可以匹配 colour 和 color |
+ | 匹配前面的字符一次或多次 | go+gle,该表达式可以匹配的范围从 gogle 到 goo…gle |
* | 匹配前面的字符零次或多次 | go*gle,该表达式可以匹配的范围从 ggle 到 goo…gle |
{n} | 匹配前面的字符 n 次 | go{2}gle,该表达式只匹配 google |
{n,} | 匹配前面的字符最少 n 次 | go{2,}gle,该表达式可以匹配的范围从 google 到 goo…gle |
{n,m} | 匹配前面的字符最少 n 次,最多 m 次 | employe{0,2},该表达式可以匹配 employ、employe 和 employee |
-
字符类:匹配数字和字符除了可以用 ‘\d’ 和 ‘\w’ 之外,像 [aeiou] 可以匹配任意一个英文元音字母,可以轻松制定一个字符范围。如果想匹配字符串中任意一个汉字,可以使用 [\u4e00-\u9fa5],如果要匹配连续多个汉字,可以使用 [\u4e00-\u9fa5]+;
-
排除字符:’^’ 字符如果放在方括号中,表示排除的意思。例如:
[^a-zA-Z]
该表达式用于匹配一个不是字母的字符; -
选择字符:当包含着条件选择的逻辑时,就需要使用选择字符 ‘|’,该字符可以理解为 ‘或’。例如:
(^\d{15}$) | (^\d{18}$) | (^\d{17})(\d|X|x)$
该字符串的意思是可以匹配 15 位数字,或者 18 位数字,或者 17 位数字和最后一位(可以是数字、x 或者 X); -
转义字符:正则表达式中的转义字符 ‘\’ 和 Python 字符串中的转义字符大同小异,都是将特殊字符变为普通字符;
-
分组:在正则表达式中,小括号的作用有两个,一个是改变限定符的作用范围,还有就是分组。例如:
(\.[0-9]{1,3}){3}
就是对小组中内容的重复操作;
使用 re 模块实现正则表达式操作
Python 中提供了 re 模块,用于实现正则表达式的操作。使用前先导入:import re
- 匹配字符串
- 使用 match() 方法进行匹配
match() 方法用于从字符串的开始处进行匹配,如果在起始位置匹配成功,则返回 Match 对象,否则返回 None,其语法格式如下:
re.match(pattern, string, [flags])
pattern:表示模式字符串,由要匹配的正则表达式转换而来;
string:表示要匹配的字符串;
flags:可选参数,表示标志位,用于控制匹配方向,如是否区分字母大小写。常用的标志如下表所示:
标志 | 说明 |
---|---|
A 或 ASCII | 对于 \w、\W、\b、\B、\d、\D、\s 和 \S 只进行 ASCII 匹配(仅适用于 Python 3.x) |
I 或 IGNORECASE | 执行不区分字母大小写的匹配 |
M 或 MULTILINE | 将 ^ 和 $ 用于包括整个字符串的开始和结尾的每一行(默认情况下,仅适用于整个字符串的开始和结尾处) |
S 或 DOTALL | 使用 ‘.’ 字符匹配所有字符,包括换行符 |
X 或 VERBOSE | 忽略模式字符串中未转义的空格和注释 |
示例1:
import re
pattern = r'mr_\w+' # 模式字符串
string = '项目名称:MR_SHOP mr_shop' # 要匹配的字符串
match = re.match(pattern, string, re.I) # 匹配字符串,不区分大小写
print(match)
string = 'MR_SHOP mr_shop'
match = re.match(pattern, string, re.I)
print(match)
print('匹配值得起始位置:', match.start())
print('匹配值得结束位置:', match.end())
print('匹配位置的元组:', match.span())
print('要匹配的字符串:', match.string)
print('匹配数据:', match.group())
上述例子的运行结果为:
None
<re.Match object; span=(0, 7), match='MR_SHOP'>
匹配值得起始位置: 0
匹配值得结束位置: 7
匹配位置的元组: (0, 7)
要匹配的字符串: MR_SHOP mr_shop
匹配数据: MR_SHOP
示例2:
import re
pattern = r'(13[4-9]\d{8})$|(15[01289]\d{8})$'
mobile = '13222222222'
match = re.match(pattern, mobile)
if match == None:
print(mobile, "不是有效的中国移动手机号码。")
else:
print(mobile, "是有效的中国移动手机号码。")
mobile = '15800000000'
if match == None:
print(mobile, "不是有效的中国移动手机号码。")
else:
print(mobile, "是有效的中国移动手机号码。")
上述例子的运行结果为:
13222222222 不是有效的中国移动手机号码。
15800000000 不是有效的中国移动手机号码。
- 使用 search() 方法进行匹配
search() 方法与 match() 方法的区别在于,match 是只在起始位置匹配,而 search 是在整个字符串中搜索,其语法格式和 match 一致,如下:
re.search(pattern, string, [flags])
示例1:
import re
pattern = r'mr_\w+' # 模式字符串
string = '项目名称:MR_SHOP mr_shop' # 要匹配的字符串
match = re.search(pattern, string, re.I) # 匹配字符串,不区分大小写
print(match)
string = 'MR_SHOP mr_shop'
match = re.search(pattern, string, re.I)
print(match)
上述例子的运行结果为:
<re.Match object; span=(5, 12), match='MR_SHOP'>
<re.Match object; span=(0, 7), match='MR_SHOP'>
示例2:
import re
pattern = r'(黑客)|(抓包)|(监听)|(Trojan)'
about = '我是一名程序员,我喜欢看黑客方面的图书,想研究一下 Trojan'
match = re.search(pattern, about)
if match == None:
print(about, '@ 安全!')
else:
print(about, '@ 出现了危险词汇!')
about = '我是一名程序员,我喜欢看计算机网络方面的图书,喜欢开发网站'
match = re.search(pattern, about)
if match == None:
print(about, '@ 安全!')
else:
print(about, '@ 出现了危险词汇!')
上述例子的运行结果为:
我是一名程序员,我喜欢看黑客方面的图书,想研究一下 Trojan @ 出现了危险词汇!
我是一名程序员,我喜欢看计算机网络方面的图书,喜欢开发网站 @ 安全!
- 使用 findall() 方法进行匹配
findall() 方法用于在整个字符串中搜索所有符合正则表达式的字符串,并以列表的形式返回。如果匹配失败,则返回空列表,其语法格式和 match、search 一致,如下:
re.findall(pattern, string, [flags])
示例1:
import re
pattern = r'mr_\w+' # 模式字符串
string = '项目名称:MR_SHOP mr_shop' # 要匹配的字符串
match = re.findall(pattern, string, re.I) # 匹配字符串,不区分大小写
print(match)
string = 'MR_SHOP mr_shop'
match = re.findall(pattern, string) # 匹配字符串,区分大小写
print(match)
上述例子的运行结果为:
['MR_SHOP', 'mr_shop']
['mr_shop']
示例2:
import re
pattern1 = r'[1-9]{1,3}(\.[0-9]{1,3}){3}'
str = '127.0.0.1 192.168.1.66'
match = re.findall(pattern1, str)
print(match)
pattern1 = r'([1-9]{1,3}(\.[0-9]{1,3}){3})'
match = re.findall(pattern1, str)
print(match)
for item in match:
print(item[0])
上述例子的运行结果为:
['.1', '.66']
[('127.0.0.1', '.1'), ('192.168.1.66', '.66')]
127.0.0.1
192.168.1.66
注意:如果模式字符串中出现分组,那么得到的结果是根据分组进行匹配的结果。如果想获取整个模式字符串的匹配,可以将整个模式字符串使用一对小括号进行分组。然后在获取结果时,只取返回值列表的每个元素的第一个元素。
- 替换字符串
sub() 方法用于时显示字符串替换。其语法格式如下:
re.sub(pattern, repl, string, count, flags)
pattern:表示模式字符串,由要匹配的正则表达式转换而来;
repl:表示替换的字符串;
string:表示要被查找替换的原始字符串;
count:可选参数,表示模式匹配后替换的最大次数;
flags:可选参数,表示标志位,用于控制匹配方式,如是否区分字母大小写;
示例:
import re
pattern = r'1[34578]\d{9}'
string = '中奖号码为:84978981 联系电话为:13611111111'
result = re.sub(pattern, '1XXXXXXXXXX', string) # 隐藏字符串中的手机号
print(result)
pattern = r'(黑客)|(抓包)|(监听)|(Trojan)'
about = '我是一名程序员,我喜欢看黑客方面的图书,想研究一下 Trojan'
sub = re.sub(pattern, '@__@', about) # 替换出现的危险字符
print(sub)
上述例子的运行结果为:
中奖号码为:84978981 联系电话为:1XXXXXXXXXX
我是一名程序员,我喜欢看@__@方面的图书,想研究一下 @__@
- 使用正则表达式分割字符串
split() 方法用于实现根据正则表达式分割字符串,并以列表的形式返回。其作用与字符串对象的 split() 方法类似,所不同的就是分割字符由模式字符串指定,其语法格式如下:
re.split(pattern, string, [maxsplit], [flags])
示例:
import re
str = '@马云 @马化腾 @刘强东'
pattern = r'\s*@'
list = re.split(pattern, str)
print('我的好友有:')
for item in list:
if item != "":
print(item)
上述例子的运行结果为:
我的好友有:
马云
马化腾
刘强东