C++11的正则表达式基本⽤法
1. 介绍
正则表达式(Regular Expression,常简写为regex、regexp或RE)。正则表达式通常被⽤来检索、替换那些符合某个模式(规则)的⽂本。C++11开始⽀持正则表达式。
正则表达式⾮常强⼤,具体的实现算法有差异,所以会有多种实现⽅式。C++11⽀持6种正则表达式引擎。ECMAScript 是其中⽀持最多元素的引擎,也是regex默认⽀持的引擎。
ECMAScript
basic(POSIX Basic Regular Expressions)
extended(POSIX Extended Regular Expressions )
awk(POSIX awk)
grep(POSIX grep )
egrep(POSIX grep –E)
2. 正则表达式语法
正则表达式主要两部分构成,特殊字符和普通字符。
1. “.”: 匹配除"\n"之外的任何单个字符,若要匹配包括"\n"在内的任意字符,需使⽤诸如"[\s\S]"之类的模式;
2. “^”:匹配输⼊字符串的开始位置,不匹配任何字符,要匹配”^”字符本⾝,需使⽤”^”;
3. “$”:匹配输⼊字符串结尾的位置,不匹配任何字符,要匹配”$”字符本⾝,需使⽤”$”;
4. “*”: 零次或多次匹配前⾯的字符或⼦表达式,”*”等效于”{0,}”,如”^*b”可以匹配”b”、”^b”、”^^b”、…;
5. “+”: ⼀次或多次匹配前⾯的字符或⼦表达式,等效于”{1,}”,如”a+b”可以匹配”ab”、”aab”、”aaab”、…;
6. “?”: 零次或⼀次匹配前⾯的字符或⼦表达式,等效于”{0,1}”,如”a[cd]?”可以匹配”a”、”ac”、”ad”; 当此字符紧随
任何其他限定符”*”、”+”、”?”、”{n}”、”{n,}”、”{n,m}”之后时,匹配模式是"⾮贪⼼的"。"⾮贪⼼的"模式匹配搜索到的、尽可能短的字符串,⽽默认的"贪⼼的"模式匹配搜索到的、尽可能长的字符串。如,在字符串"oooo"中,"o+?“只匹配单个"o”,⽽"o+“匹配所有"o”;
7. “|”:将两个匹配条件进⾏逻辑"或"(Or)运算,如正则表达式”(him|her)”匹配"itbelongs to him"和"it belongs to her",但是不能
匹配"itbelongs to them.";
8. “\”: 将下⼀字符标记为特殊字符、⽂本、反向引⽤或⼋进制转义符,如,”n”匹配字符”n”,”\n”匹配换⾏符,序列”\”匹
配”\”,”(“匹配”(“;
9. “\w”:匹配字母或数字或下划线,任意⼀个字母或数字或下划线,即A~Z,a~z,0~9,_中任意⼀个;
10. “\W”:匹配任意不是字母、数字、下划线的字符;
11. “\s”:匹配任意的空⽩符,包括空格、制表符、换页符等空⽩字符的其中任意⼀个,与”[ \f\n\r\t\v]”等效;
12. “\S”:匹配任意不是空⽩符的字符,与”[^\f\n\r\t\v]”等效;
13. “\d”:匹配数字,任意⼀个数字,0~9中的任意⼀个,等效于”[0-9]”;
14. “\D”:匹配任意⾮数字的字符,等效于”[^0-9]”;
15. “\b”: 匹配⼀个字边界,即字与空格间的位置,也就是单词和空格之间的位置,不匹配任何字符,如,“er\b"匹配"never"中
的"er”,但不匹配"verb"中的"er";
16. “\B”: ⾮字边界匹配,“er\B"匹配"verb"中的"er”,但不匹配"never"中的"er";
17. “\f”:匹配⼀个换页符,等价于”\x0c”和”\cL”;
18. “\n”:匹配⼀个换⾏符,等价于”\x0a”和”\cJ”;
19. “\r”:匹配⼀个回车符,等价于”\x0d”和”\cM”;
20. “\t”:匹配⼀个制表符,等价于”\x09”和”\cI”;
21. “\v”:匹配⼀个垂直制表符,等价于”\x0b”和”\cK”;
22. “\cx”:匹配”x”指⽰的控制字符,如,\cM匹配Control-M或回车符,”x”的值必须在”A-Z”或”a-z”之间,如果不是这样,则
假定c就是"c"字符本⾝;
23. “{n}”:”n”是⾮负整数,正好匹配n次,如,"o{2}"与"Bob"中的"o"不匹配,但与"food"中的两个"o"匹配;
24. “{n,}”:”n”是⾮负整数,⾄少匹配n次,如,"o{2,}“不匹配"Bob"中的"o”,⽽匹配"foooood"中的所有”o”,"o{1,}“等效
于"o+”,"o{0,}“等效于"o*”;
25. “{n,m}”:”n”和”m”是⾮负整数,其中n<=m,匹配⾄少n次,⾄多m次,如,"o{1,3}"匹配"fooooood"中的头三个
o,'o{0,1}‘等效于’o?’,注意,不能将空格插⼊逗号和数字之间;如”ba{1,3}”可以匹配”ba”或”baa”或”baaa”;
26. “x|y”:匹配”x”或”y”,如,”z|food”匹配"z"或"food";”(z|f)ood”匹配"zood"或"food";
27. “[xyz]”:字符集,匹配包含的任⼀字符,如,"[abc]“匹配"plain"中的"a”;
28. “[^xyz]””:反向字符集,匹配未包含的任何字符,匹配除了”xyz”以外的任意字符,如,"[^abc]“匹配"plain"中的"p”;
29. “[a-z]”:字符范围,匹配指定范围内的任何字符,如,"[a-z]"匹配"a"到"z"范围内的任何⼩写字母;
30. “[^a-z]”:反向范围字符,匹配不在指定的范围内的任何字符,如,"[^a-z]"匹配任何不在"a"到"z"范围内的任何字符;
31. “( )”:将”(“和”)”之间的表达式定义为”组”group,并且将匹配这个表达式的字符保存到⼀个临时区域,⼀个正则表达式中最
多可以保存9个,它们可以⽤”\1”到”\9”的符号来引⽤;
32. “(pattern)”:匹配pattern并捕获该匹配的⼦表达式,可以使⽤$0…$9属性从结果”匹配”集合中检索捕获的匹配;"$0"表⽰整个
匹配,"$1"表⽰第1个⼦表达式的匹配结果。当只有⼀个⼦表达式时两者可能是相同。
33. “(?:pattern)”:匹配pattern但不捕获该匹配的⼦表达式,即它是⼀个⾮捕获匹配,不存储供以后使⽤的匹配,这对于⽤”or”字
符” (|)”组合模式部件的情况很有⽤, 如,”industr(?:y|ies)”是⽐”industry|industries”更简略的表达式;
34. “(?=pattern)”: ⾮获取匹配,正向肯定预查,在任何匹配pattern的字符串开始处匹配查字符串,该匹配不需要获取供以后使
⽤。如,“Windows(?=95|98|NT|2000)“能匹配"Windows2000"中的"Windows”,但不能匹配"Windows3.1"中
的"Windows”。预查不消耗字符,也就是说,在⼀个匹配发⽣后,在最后⼀次匹配之后⽴即开始下⼀次匹配的搜索,⽽不是从包含预查的字符之后开始;
35. “(?!pattern)”: ⾮获取匹配,正向否定预查,在任何不匹配pattern的字符串开始处匹配查字符串,该匹配不需要获取供以后使
⽤。如"Windows(?!95|98|NT|2000)“能匹配"Windows3.1"中的"Windows”,但不能匹配"Windows2000"中的"Windows";
3. 正则表达式的使⽤
⽬标序列(Target sequence)。为模式⽽搜索到的字符序列。这可以是⼆个迭代器所指定的范围、空终⽌字符串或⼀个 std::string 。
模式(Pattern)。这是正则表达式⾃⾝。它确定构成匹配者。它是从带特定语法的字符串构成的 std::basic_regex 类型对象。受⽀持的语法变体的描述见 syntax_option_type 。
匹配的数组(Matched array)。关于匹配的信息可作为 std::match_results 类型对象获取。
替换字符串(Replacement string)。这是确定如何替换匹配的字符串,受⽀持的语法变体的描述不同⽽不同。
3.1 基本类
为了⽀持宽字符和窄字符,所以正则表达式的类基本上是通过类模板来实现的。
typedef basic_regex<char> regex;// 正则表达式对象
typedef basic_regex<wchar_t> wregex;
typedef match_results<const char*> cmatch;// 标识⼀个正则表达式匹配,包含所有⼦表达式匹配(字符指针)
typedef match_results<const wchar_t *> wcmatch;
typedef match_results<string::const_iterator> smatch;// 标识⼀个正则表达式匹配,包含所有⼦表达式匹配(字符串)
typedef match_results<wstring::const_iterator> wsmatch;
typedef sub_match<const char*> csub_match;// 标识⼦表达式所匹配的字符序列
typedef sub_match<const wchar_t *> wcsub_match;
3.2. 算法
算法将封装于 regex 的正则表达式应⽤到字符的⽬标序列,算法主要是由函数模板来实现的。
regex_match,试图匹配正则表达式到整个字符序列 。
regex_search,试图匹配正则表达式到字符序列的任何部分 。
regex_replace,以格式化的替换⽂本来替换正则表达式匹配的出现位置 。
3.3. 迭代器
迭代器⽤于遍历在序列中到的匹配正则表达式的整个集合。
regex_iterator,在字符序列中通过所有正则表达式匹配迭代 。
regex_token_iterator,通过在给定的字符串中所有正则表达式匹配中的指定⼦表达式,或通过不匹配的⼦串迭代 。
3.4 异常
regex_error定义⼀个对象抛出来⾃正则表达式库 的异常。
4. ⽰例
以下代码使⽤VS2010进⾏编译测试。
4.1. regex_match
#include"stdafx.h"
#include<regex>// Must be included
#include<string>
#include<iostream>
using namespace std;
int_tmain(int argc, _TCHAR* argv[])
{
// .通配符,⼏个代表⼏个字符
std::string strSrc ="Simple";
std::regex rePattern1("Simpl.");
cout<<boolalpha<<std::regex_match(strSrc, rePattern1)<<endl;// true
std::regex rePattern2("Simp..");
cout<<boolalpha<<std::regex_match(strSrc, rePattern2)<<endl;// true
// ^在regex_match中的作⽤⽆法体现,因为regex_match就要求必须从开始匹配
std::regex rePattern3(".impl.");
cout<<boolalpha<<std::regex_match(strSrc, rePattern3)<<endl;// true
std::regex rePattern4("^.impl.");
cout<<boolalpha<<std::regex_match(strSrc, rePattern4)<<endl;// true
// regex_match可以⽤作单纯的匹配判断,也可以匹配获得具体的结果
// 匹配的结果存放在smatch中.smatch中0索引存放完整匹配的结果,1存放第1个()匹配的结果
// 从smatch中取元素,既可以⽤[],也可以⽤str(idx)
std::smatch matchRes1;
strSrc ="";
std::regex rePattern5("(foot)\\.txt");// \\.使⽤转义字符
std::regex rePattern5("(foot)\\.txt");// \\.使⽤转义字符
cout<<boolalpha<<std::regex_match(strSrc, matchRes1, rePattern5)<<endl;// true
cout<<matchRes1[0]<<":"<<matchRes1[1]<<endl;// :foot
std::regex rePattern6("(....)\\.txt");// \\.使⽤转义字符
cout<<boolalpha<<std::regex_match(strSrc, matchRes1, rePattern6)<<endl;// true
cout<<matchRes1[0]<<":"<<matchRes1[1]<<endl;// :foot
cout<<matchRes1[0]<<":"<<matchRes1.str(1)<<endl;// :foot
std::ssub_match ssMatch = matchRes1[1];
// ssMatch⽀持强制转换成string类型,和ssMatch.str()等价
cout<<matchRes1[0]<<":"<<ssMatch<<endl;// :foot
cout<<matchRes1[0]<<":"<<ssMatch.str()<<endl;// :foot
// *表⽰匹配前⾯的o,0或多个均可。即strSrc为ft.,均匹配成功
std::regex rePattern7("fo*t\\.txt");// \\.使⽤转义字符
cout<<boolalpha<<std::regex_match(strSrc, matchRes1, rePattern7)<<endl;// true
// +表⽰匹配前⾯的o,1或多个均可。即strSrc为,均匹配成功,ft.txt匹配不成功
std::regex rePattern8("fo+t\\.txt");// \\.使⽤转义字符
cout<<boolalpha<<std::regex_match(strSrc, matchRes1, rePattern8)<<endl;// true
// ?表⽰匹配前⾯的o,0或1个均可。即strSrc为ft.均匹配成功,匹配不成功
std::regex rePattern9("fo?t\\.(txt)");// \\.使⽤转义字符
cout<<boolalpha<<std::regex_match(strSrc, matchRes1, rePattern9)<<endl;// false
// 下⾯有两个括号,即对应两个匹配元素[1],[2]
std::regex rePattern10("(foo?t)\\.(txt)");// \\.使⽤转义字符
cout<<boolalpha<<std::regex_match(strSrc, matchRes1, rePattern10)<<endl;// true
cout<<matchRes1[0]<<":"<<matchRes1.str(1)<<":"<<matchRes1[2]<<endl;// :foot:txt
// (ab)是⼦表达式,(ab)+表⽰匹配1个或多个ab.
strSrc ="";正则表达式获取括号内容
std::regex rePattern11("(ab)+\\.(txt)");// 可匹配ab.,等
cout<<boolalpha<<std::regex_match(strSrc, matchRes1, rePattern11)<<endl;// true
cout<<matchRes1[0]<<":"<<matchRes1.str(1)<<":"<<matchRes1[2]<<endl;// :ab:txt
// (ab|cd)是⼦表达式,(ab|cd)+表⽰匹配1个或多个ab或cd.
strSrc ="";
std::regex rePattern12("(ab|cd)+\\.(txt)");// 可匹配ab.,等
cout<<boolalpha<<std::regex_match(strSrc, matchRes1, rePattern12)<<endl;// true
cout<<matchRes1[0]<<":"<<matchRes1.str(1)<<":"<<matchRes1.str(2)<<endl;// :ab:txt // {n}表⽰匹配前⾯的字符或⼦表达式n次
strSrc ="";
std::regex rePattern13("(ab){2}\\.(txt)");// 只匹配等
cout<<boolalpha<<std::regex_match(strSrc, matchRes1, rePattern13)<<endl;// true
cout<<matchRes1[0]<<":"<<matchRes1.str(1)<<":"<<matchRes1.str(2)<<endl;// :ab:txt // [abc]表⽰匹配字符集中的字符
strSrc ="";
std::regex rePattern14("[abc]\\.(txt)");// 只匹配a.,c.txt
cout<<boolalpha<<std::regex_match(strSrc, matchRes1, rePattern14)<<endl;// flase
// [abc]+表⽰匹配1个或多个字符集中的字符
std::regex rePattern15("[abcde]+\\.(txt)");// 只要.txt之前的字符属于字符集均匹配
cout<<boolalpha<<std::regex_match(strSrc, matchRes1, rePattern15)<<endl;// true
cout<<matchRes1[0]<<":"<<matchRes1.str(1)<<endl;// :txt
// 组([^aBcD]+)匹配到a即停⽌.[^aBcD]表⽰匹配⾮集合中的字符,[^A-Z]表⽰匹配A-Z之外的字符
strSrc ="";
std::regex rePattern16("([^aBcD]+)[^A-Z]+\\.(txt)");// 只要.txt之前的字符属于字符集均匹配
cout<<boolalpha<<std::regex_match(strSrc, matchRes1, rePattern16)<<endl;// true
cout<<matchRes1[0]<<":"<<matchRes1.str(1)<<endl;// :AbCdA23
// [a-zA-Z0-9]{1,20},字符集内的字符,最少1次,最多20次.⽤来控制数字或字母的个数
strSrc ="AbCdA23ab4t";
std::regex rePattern17("[a-zA-Z0-9]{1,20}");
cout<<boolalpha<<std::regex_match(strSrc, rePattern17)<<endl;// true
// regex对象默认是⼤⼩写敏感的,regex::icase即指定⼤⼩写不敏感
cout <<boolalpha<<regex_match("aaaAAA",regex("a*", regex::icase))<< endl;// true
cout <<boolalpha<<regex_match("aaaAAA",regex("a*"))<< endl;// false
return0;
}
4.2. regex_search
#include"stdafx.h"
#include<regex>// Must be included
#include<string>
#include<iostream>
using namespace std;
int_tmain(int argc, _TCHAR* argv[])
{
std::string strSrc ="Color is #ffAB11";
// regex_serch并不要求整个匹配,只要匹配现有的pattern即为成功
std::regex rePattern1("#([a-f]{2})");
std::cout<<std::boolalpha<<std::regex_search(strSrc, rePattern1)<<std::endl;
// smatch存放匹配的结果,索引0存放的是完整的结果,索引1存放的是第1个()表达式匹配的结果
std::smatch matchRes2;
std::regex rePattern2("#([a-f]{2})");
std::cout<<std::boolalpha<<std::regex_search(strSrc, matchRes2, rePattern2)<<std::endl;
cout<<matchRes2[0]<<":"<<matchRes2.str(1)<<endl;// #ff:ff
// [a-f]{2}表⽰有2个a-f之间的字符,[A-F]+表⽰有1个或多个A-F之间的字符
std::smatch matchRes3;
std::regex rePattern3("#([a-f]{2})([A-F]+)");
std::cout<<std::boolalpha<<std::regex_search(strSrc, matchRes3, rePattern3)<<std::endl;
cout<<matchRes3.str(0)<<":"<<matchRes3.str(1)<<":"<<matchRes3.str(2)<<endl;// #ffAB:ff:AB
cout<<matchRes3[0]<<":"<<matchRes3[1]<<":"<<matchRes3[2]<<endl;// #ffAB:ff:AB
// prefix表⽰搜索匹配字符串之前未匹配的字符,suffix表⽰搜索匹配字符串之后未匹配的字符
cout<<matchRes3.prefix()<<":"<<matchRes3.suffix()<<endl;// Color is:11
// [0-9]*表⽰可以匹配0个或多个0-9的数字字符
std::smatch matchRes4;
std::regex rePattern4("#([a-f]{2})([A-F]+)([0-9]*)");
std::cout<<std::boolalpha<<std::regex_search(strSrc, matchRes4, rePattern4)<<std::endl;
cout<<matchRes4[0]<<":"<<matchRes4[1]<<":"<<matchRes4[2]<<":"<<matchRes4[3]<<endl;// #ffAB11:ff:AB:11
// prefix表⽰搜索匹配字符串之前未匹配的字符,suffix表⽰搜索匹配字符串之后未匹配的字符(此处为空,即没有剩余未匹配的字符) cout<<matchRes4.prefix()<<":"<<matchRes4.suffix()<<endl;// Color is:
// ^要求必须是从最开始即满⾜匹配
std::regex rePattern5("^#([a-f]{2})([A-F]+)([0-9]*)");
std::smatch matchRes5;
std::cout<<std::boolalpha<<std::regex_search(strSrc, matchRes5, rePattern5)<<std::endl;// false
// ^.+能够保证从最开始即满⾜匹配,$要求必须匹配到最后
std::regex rePattern6("^.+#([a-f]{2})([A-F]+)([0-9]*)$");
std::smatch matchRes6;
std::cout<<std::boolalpha<<std::regex_search(strSrc, matchRes6, rePattern6)<<std::endl;// true
return0;
}
4.3. regex_replace
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论