正则表达式RE以及Python, C++实现
参考自:
https://www.runoob.com/regexp/regexp-tutorial.html
https://www.runoob.com/python/python-reg-expressions.html
在线测试RE网站:
1. 简介
正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符")。
正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。
许多程序设计语言都支持利用正则表达式进行字符串操作。
2. 语法
2.1 普通字符
字符 | 描述 |
---|---|
[ABC] |
匹配 [...] 中的所有字符,例如 [aeiou] 匹配字符串 "google runoob taobao" 中所有的 e o u a 字母。 ![]() |
[^ABC] |
匹配除了 [...] 中字符的所有字符,例如 [^aeiou] 匹配字符串 "google runoob taobao" 中除了 e o u a 字母的所有字母。 ![]() |
[A-Z] |
[A-Z] 表示一个区间,匹配所有大写字母,[a-z] 表示所有小写字母。 ![]() |
. |
匹配除换行符(\n、\r)之外的任何单个字符,相等于 [^\n\r]。 ![]() |
[\s\S] |
匹配所有。\s 是匹配所有空白符,包括换行,\S 非空白符,包括换行。 ![]() |
\w |
匹配字母、数字、下划线。等价于 [A-Za-z0-9_] ![]() |
以下字符需要转义:
字符 | 描述 |
---|---|
\cx | 匹配由x指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。 |
\f | 匹配一个换页符。等价于 \x0c 和 \cL。 |
\n | 匹配一个换行符。等价于 \x0a 和 \cJ。 |
\r | 匹配一个回车符。等价于 \x0d 和 \cM。 |
\s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。注意 Unicode 正则表达式会匹配全角空格符。 |
\S | 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 |
\t | 匹配一个制表符。等价于 \x09 和 \cI。 |
\v | 匹配一个垂直制表符。等价于 \x0b 和 \cK。 |
2.2 特殊字符(元字符)
特别字符 | 描述 |
---|---|
$ | 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 字符本身,请使用 $。 |
( ) | 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 。 |
* | 匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 \*。 |
+ | 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+。 |
. | 匹配除换行符 \n 之外的任何单字符。要匹配 . ,请使用 \. 。 |
[ | 标记一个中括号表达式的开始。要匹配 [,请使用 \[。 |
? | 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?。 |
\ | 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, 'n' 匹配字符 'n'。'\n' 匹配换行符。序列 '\\' 匹配 "\",而 '\(' 则匹配 "("。 |
^ | 匹配输入字符串的开始位置,除非在方括号表达式中使用,当该符号在方括号表达式中使用时,表示不接受该方括号表达式中的字符集合。要匹配 ^ 字符本身,请使用 \^。 |
{ | 标记限定符表达式的开始。要匹配 {,请使用 \{。 |
| | 指明两项之间的一个选择。要匹配 |,请使用 \|。 |
2.3 限定符
字符 | 描述 |
---|---|
* | 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。 |
+ | 匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。 |
? | 匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 、 "does" 中的 "does" 、 "doxy" 中的 "do" 。? 等价于 {0,1}。 |
{n} | n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。 |
{n,} | n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。 |
{n,m} | m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。 |
2.4 定位符
字符 | 描述 |
---|---|
^ | 匹配输入字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与 \n 或 \r 之后的位置匹配。 |
$ | 匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与 \n 或 \r 之前的位置匹配。 |
\b | 匹配一个单词边界,即字与空格间的位置。 |
\B | 非单词边界匹配。 |
2.5 选择
用圆括号 () 将所有选择项括起来,相邻的选择项之间用 | 分隔。
() 表示捕获分组,() 会把每个分组里的匹配的值保存起来, 多个匹配值可以通过数字 n 来查看(n 是一个数字,表示第 n 个捕获组的内容)。
- exp1(?=exp2):查找 exp2 前面的 exp1。
- (?<=exp2)exp1:查找 exp2 后面的 exp1。
- exp1(?!exp2):查找后面不是 exp2 的 exp1。
- (?<!exp2)exp1:查找前面不是 exp2 的 exp1。
2.6 反向捕获
对一个正则表达式模式或部分模式两边添加圆括号将导致相关匹配存储到一个临时缓冲区中,所捕获的每个子匹配都按照在正则表达式模式中从左到右出现的顺序存储。缓冲区编号从 1 开始,最多可存储 99 个捕获的子表达式。每个缓冲区都可以使用 \n 访问,其中 n 为一个标识特定缓冲区的一位或两位十进制数。
可以使用非捕获元字符 ?:、?= 或 ?! 来重写捕获,忽略对相关匹配的保存。
2.7 修饰符
位于表达式以外
修饰符 | 含义 | 描述 |
---|---|---|
i | ignore - 不区分大小写 | 将匹配设置为不区分大小写,搜索时不区分大小写: A 和 a 没有区别。 |
g | global - 全局匹配 | 查找所有的匹配项。 |
m | more - 多行匹配 | 使边界字符 ^ 和 $ 匹配每一行的开头和结尾,记住是多行,而不是整个字符串的开头和结尾。 |
s | 特殊字符圆点 . 中包含换行符 \n | 默认情况下的圆点 . 是 匹配除换行符 \n 之外的任何字符,加上 s 修饰符之后, . 中包含换行符 \n。 |
3. Python中的正则表达式re库
- re.match
尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
re.match(pattern, string, flags=0)
其中,flags是标志位修饰符,如下表:
修饰符 | 描述 |
---|---|
re.I | 使匹配对大小写不敏感 |
re.L | 做本地化识别(locale-aware)匹配 |
re.M | 多行匹配,影响 ^ 和 $ |
re.S | 使 . 匹配包括换行在内的所有字符 |
re.U | 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B. |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
- re.search
re.search 扫描整个字符串并返回第一个成功的匹配。
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。
1 #!/usr/bin/python 2 import re 3 4 line = "Cats are smarter than dogs"; 5 6 matchObj = re.match( r'dogs', line, re.M|re.I) 7 if matchObj: 8 print "match --> matchObj.group() : ", matchObj.group() 9 else: 10 print "No match!!" 11 12 matchObj = re.search( r'dogs', line, re.M|re.I) 13 if matchObj: 14 print "search --> searchObj.group() : ", matchObj.group() 15 else: 16 print "No match!!"
- re.compile
1 >>>import re 2 >>> pattern = re.compile(r'\d+') # 用于匹配至少一个数字 3 >>> m = pattern.match('one12twothree34four') # 查找头部,没有匹配 4 >>> print m 5 None 6 >>> m = pattern.match('one12twothree34four', 2, 10) # 从'e'的位置开始匹配,没有匹配 7 >>> print m 8 None 9 >>> m = pattern.match('one12twothree34four', 3, 10) # 从'1'的位置开始匹配,正好匹配 10 >>> print m # 返回一个 Match 对象 11 <_sre.SRE_Match object at 0x10a42aac0> 12 >>> m.group(0) # 可省略 0 13 '12' 14 >>> m.start(0) # 可省略 0 15 3 16 >>> m.end(0) # 可省略 0 17 5 18 >>> m.span(0) # 可省略 0 19 (3, 5)
compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。
- re.findall
在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。
1 # -*- coding:UTF8 -*- 2 3 import re 4 5 pattern = re.compile(r'\d+') # 查找数字 6 result1 = pattern.findall('runoob 123 google 456') 7 result2 = pattern.findall('run88oob123google456', 0, 10)
Output:
['123', '456']
['88', '12']
- re.finditer
和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。
1 # -*- coding: UTF-8 -*- 2 3 import re 4 5 it = re.finditer(r"\d+","12a32bc43jf3") 6 for match in it: 7 print (match.group() )
- re.split
split 方法按照能够匹配的子串将字符串分割后返回列表
1 >>>import re 2 >>> re.split('\W+', 'runoob, runoob, runoob.') 3 ['runoob', 'runoob', 'runoob', ''] 4 >>> re.split('(\W+)', ' runoob, runoob, runoob.') 5 ['', ' ', 'runoob', ', ', 'runoob', ', ', 'runoob', '.', ''] 6 >>> re.split('\W+', ' runoob, runoob, runoob.', 1) 7 ['', 'runoob, runoob, runoob.'] 8 9 >>> re.split('a*', 'hello world') # 对于一个找不到匹配的字符串而言,split 不会对其作出分割 10 ['hello world']
- re.sub
检索和替换
re.sub(pattern, repl, string, count=0, flags=0)
4. C++中的正则表达式匹配
C++中的std库有方法 std::regex 可以判断字符串是否匹配,匹配结果返回一个bool值。
示例:用正则表达式判断一个密码是否有效,密码规则:
(1)必须6位或以上
(2)所有字符都是有效字符
(3)至少带有一个数字,一个大写字母,一个小写字母,一个特殊字符
1 bool isPasswordValid(std::string& strPassword) 2 { 3 std::regex regPattern("[a-zA-Z0-9\\$\\*_#]{6,}"); // contain at 6 characters in the specified set 4 std::regex regPattern1(".*([0-9]).*"); // contain at least one digits 5 std::regex regPattern2(".*([a-z]).*"); // contain at least one lowercase letter 6 std::regex regPattern3(".*([A-Z]).*"); // contain at least one uppercase letter 7 std::regex regPattern4(".*([@\\$\\*_#]).*"); // contain at least one specified special letter 8 9 BOOL bPassFlag = std::regex_match(strPassword,regPattern); 10 BOOL bDigFlag = std::regex_match(strPassword, regPattern1); 11 BOOL bLowFlag = std::regex_match(strPassword, regPattern2); 12 BOOL bUppFlag = std::regex_match(strPassword, regPattern3); 13 BOOL bSpeFlag = std::regex_match(strPassword, regPattern4); 14 15 if(bPassFlag && ((bDigFlag?1:0)+(bLowFlag?1:0)+(bUppFlag?1:0)+(bSpeFlag?1:0) >= 3)) 16 return true; 17 else 18 return false; 19 }
std中还提供其它方法:
std::regex_search 搜索并返回匹配到的字符串
std::regex_replace 对搜索到的字符串进行替换
参考:https://www.geeksforgeeks.org/regex-regular-expression-in-c/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具