std::regex reg("(\\d{4})-(0\\d{1}|1[0-2])-(0\\d{1}|[12]\\d{1}|3[01])\\s(0\\d{1}|1\\d{1}|2[0-3]):[0-5]\\d{1}:([0-5]\\d{1})");
bool ff = regex_match("2015-03-05 12:08:20", reg);//ff=true
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. 正则表达式语法
正则表达式主要两部分构成,特殊字符和普通字符。
-
“.”: 匹配除"\n"之外的任何单个字符,若要匹配包括"\n"在内的任意字符,需使用诸如"[\s\S]"之类的模式;
-
“”:匹配输入字符串的开始位置,不匹配任何字符,要匹配””字符本身,需使用”^”;
-
“ ” : 匹 配 输 入 字 符 串 结 尾 的 位 置 , 不 匹 配 任 何 字 符 , 要 匹 配 ” ”:匹配输入字符串结尾的位置,不匹配任何字符,要匹配” ”:匹配输入字符串结尾的位置,不匹配任何字符,要匹配””字符本身,需使用”$”;
-
“”: 零次或多次匹配前面的字符或子表达式,””等效于”{0,}”,如”*b”可以匹配”b”、”b”、”^^b”、…;
-
“+”: 一次或多次匹配前面的字符或子表达式,等效于”{1,}”,如”a+b”可以匹配”ab”、”aab”、”aaab”、…;
-
“?”: 零次或一次匹配前面的字符或子表达式,等效于”{0,1}”,如”a[cd]?”可以匹配”a”、”ac”、”ad”; 当此字符紧随任何其他限定符”*”、”+”、”?”、”{n}”、”{n,}”、”{n,m}”之后时,匹配模式是"非贪心的"。"非贪心的"模式匹配搜索到的、尽可能短的字符串,而默认的"贪心的"模式匹配搜索到的、尽可能长的字符串。如,在字符串"oooo"中,"o+?“只匹配单个"o”,而"o+“匹配所有"o”;
-
“|”:将两个匹配条件进行逻辑"或"(Or)运算,如正则表达式”(him|her)”匹配"itbelongs to him"和"it belongs to her",但是不能匹配"itbelongs to them.";
-
“\”: 将下一字符标记为特殊字符、文本、反向引用或八进制转义符,如,”n”匹配字符”n”,”\n”匹配换行符,序列”\”匹配”\”,”(“匹配”(“;
-
“\w”:匹配字母或数字或下划线,任意一个字母或数字或下划线,即AZ,az,0~9,_中任意一个;
-
“\W”:匹配任意不是字母、数字、下划线的字符;
-
“\s”:匹配任意的空白符,包括空格、制表符、换页符等空白字符的其中任意一个,与”[ \f\n\r\t\v]”等效;
-
“\S”:匹配任意不是空白符的字符,与”[^\f\n\r\t\v]”等效;
-
“\d”:匹配数字,任意一个数字,0~9中的任意一个,等效于”[0-9]”;
-
“\D”:匹配任意非数字的字符,等效于”[^0-9]”;
-
“\b”: 匹配一个字边界,即字与空格间的位置,也就是单词和空格之间的位置,不匹配任何字符,如,“er\b"匹配"never"中的"er”,但不匹配"verb"中的"er";
-
“\B”: 非字边界匹配,“er\B"匹配"verb"中的"er”,但不匹配"never"中的"er";
-
“\f”:匹配一个换页符,等价于”\x0c”和”\cL”;
-
“\n”:匹配一个换行符,等价于”\x0a”和”\cJ”;
-
“\r”:匹配一个回车符,等价于”\x0d”和”\cM”;
-
“\t”:匹配一个制表符,等价于”\x09”和”\cI”;
-
“\v”:匹配一个垂直制表符,等价于”\x0b”和”\cK”;
-
“\cx”:匹配”x”指示的控制字符,如,\cM匹配Control-M或回车符,”x”的值必须在”A-Z”或”a-z”之间,如果不是这样,则假定c就是"c"字符本身;
-
“{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}”:”n”和”m”是非负整数,其中n<=m,匹配至少n次,至多m次,如,"o{1,3}"匹配"fooooood"中的头三个o,'o{0,1}‘等效于’o?’,注意,不能将空格插入逗号和数字之间;如”ba{1,3}”可以匹配”ba”或”baa”或”baaa”;
-
“x|y”:匹配”x”或”y”,如,”z|food”匹配"z"或"food";”(z|f)ood”匹配"zood"或"food";
-
“[xyz]”:字符集,匹配包含的任一字符,如,"[abc]“匹配"plain"中的"a”;
-
“[xyz]””:反向字符集,匹配未包含的任何字符,匹配除了”xyz”以外的任意字符,如,"[abc]“匹配"plain"中的"p”;
-
“[a-z]”:字符范围,匹配指定范围内的任何字符,如,"[a-z]"匹配"a"到"z"范围内的任何小写字母;
-
“[a-z]”:反向范围字符,匹配不在指定的范围内的任何字符,如,"[a-z]"匹配任何不在"a"到"z"范围内的任何字符;
-
“( )”:将”(“和”)”之间的表达式定义为”组”group,并且将匹配这个表达式的字符保存到一个临时区域,一个正则表达式中最多可以保存9个,它们可以用”\1”到”\9”的符号来引用;
-
“(pattern)”:匹配pattern并捕获该匹配的子表达式,可以使用$0…$9属性从结果”匹配”集合中检索捕获的匹配;"$0"表示整个匹配,"$1"表示第1个子表达式的匹配结果。当只有一个子表达式时两者可能是相同。
-
“(?:pattern)”:匹配pattern但不捕获该匹配的子表达式,即它是一个非捕获匹配,不存储供以后使用的匹配,这对于用”or”字符” (|)”组合模式部件的情况很有用, 如,”industr(?:y|ies)”是比”industry|industries”更简略的表达式;
-
“(?=pattern)”: 非获取匹配,正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。如,“Windows(?=95|98|NT|2000)“能匹配"Windows2000"中的"Windows”,但不能匹配"Windows3.1"中的"Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始;
-
“(?!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)。这是确定如何替换匹配的字符串,受支持的语法变体的描述不同而不同。
#include <regex> // Must be included
#include <string>
#include <iostream>
using namespace std;
int main(int argc, char* 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 = "foot.txt";
std::regex rePattern5("(foot)\\.txt"); // \\.使用转义字符
cout << boolalpha << std::regex_match(strSrc, matchRes1, rePattern5) << endl; // true
cout << matchRes1[0] << ":" << matchRes1[1] << endl; // foot.txt:foot
std::regex rePattern6("(....)\\.txt"); // \\.使用转义字符
cout << boolalpha << std::regex_match(strSrc, matchRes1, rePattern6) << endl; // true
cout << matchRes1[0] << ":" << matchRes1[1] << endl; // foot.txt:foot
cout << matchRes1[0] << ":" << matchRes1.str(1) << endl; // foot.txt:foot
std::ssub_match ssMatch = matchRes1[1];
// ssMatch支持强制转换成string类型,和ssMatch.str()等价
cout << matchRes1[0] << ":" << ssMatch << endl; // foot.txt:foot
cout << matchRes1[0] << ":" << ssMatch.str() << endl; // foot.txt:foot
// *表示匹配前面的o,0或多个均可。即strSrc为ft.txt,fot.txt,foot.txt均匹配成功
std::regex rePattern7("fo*t\\.txt"); // \\.使用转义字符
cout << boolalpha << std::regex_match(strSrc, matchRes1, rePattern7) << endl; // true
// +表示匹配前面的o,1或多个均可。即strSrc为fot.txt,foot.txt均匹配成功,ft.txt匹配不成功
std::regex rePattern8("fo+t\\.txt"); // \\.使用转义字符
cout << boolalpha << std::regex_match(strSrc, matchRes1, rePattern8) << endl; // true
// ?表示匹配前面的o,0或1个均可。即strSrc为ft.txt,fot.txt均匹配成功,foot.txt匹配不成功
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:foot:txt
// (ab)是子表达式,(ab)+表示匹配1个或多个ab.
strSrc = "abab.txt";
std::regex rePattern11("(ab)+\\.(txt)"); // 可匹配ab.txt,abab.txt,ababab.txt等
cout << boolalpha << std::regex_match(strSrc, matchRes1, rePattern11) << endl; // true
cout << matchRes1[0] << ":" << matchRes1.str(1) << ":" << matchRes1[2] << endl; // abab.txt:ab:txt
// (ab|cd)是子表达式,(ab|cd)+表示匹配1个或多个ab或cd.
strSrc = "abcdab.txt";
std::regex rePattern12("(ab|cd)+\\.(txt)"); // 可匹配ab.txt,cd.txt,abcde.txt等
cout << boolalpha << std::regex_match(strSrc, matchRes1, rePattern12) << endl; // true
cout << matchRes1[0] << ":" << matchRes1.str(1) << ":" << matchRes1.str(2) << endl; // abcdab.txt:ab:txt
// {n}表示匹配前面的字符或子表达式n次
strSrc = "abab.txt";
std::regex rePattern13("(ab){2}\\.(txt)"); // 只匹配abab.txt等
cout << boolalpha << std::regex_match(strSrc, matchRes1, rePattern13) << endl; // true
cout << matchRes1[0] << ":" << matchRes1.str(1) << ":" << matchRes1.str(2) << endl; // abab.txt:ab:txt
// [abc]表示匹配字符集中的字符
strSrc = "abcd.txt";
std::regex rePattern14("[abc]\\.(txt)"); // 只匹配a.txt,b.txt,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; // abcd.txt:txt
// 组([^aBcD]+)匹配到a即停止.[^aBcD]表示匹配非集合中的字符,[^A-Z]表示匹配A-Z之外的字符
strSrc = "AbCdA23ab4.txt";
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; // AbCdA23ab4.txt: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
return 0;
}
参考:C++11的正则表达式基本用法
参考:
参考: