C++正则表达式

时间:2021-01-24 05:56:20

环境:win732位旗舰版、VS2010旗舰版

使用正则表达式检索、替换那些符合某个模式的文本是非常方便的,这样就不用自己写查找的算法了^^。

 

#include <string>
#include <regex>
#include <ctime>
#include <iostream>

using namespace std;
//////////////////////////////////////////////////////////////////////////
//特殊含义字符
//.除'\n'外任意单个字符
//[]字符集
//{}计数
//()子模式
//*0个或多个
//+一个或多个
//?0个或一个
//|或
//^行的开始;否定
//$行的结束
//字符集
//\d一个十进制数字
//\l一个小写字母
//\s一个空白符(空格/制表符)
//\u一个大小字母
//\w一个字母(A-Za-z)或数字(0-9)或下划线(_)
//\D除了\d之外的字符
//\L除了\l之外的字符
//\S除了\s之外的字符
//\U除了\u之外的字符
//\W除了\w之外的字符
//重复
//{n}严格重复n次
//{n,}重复n次或更多次
//{n,m}重复n-m次
//*{0,}
//+{1,}
//?{0,1}
//////////////////////////////////////////////////////////////////////////

//辅助函数
void Print(std::smatch& sm)
{
std::string s;

if (sm.empty())
return;
//显示匹配的字符串
cout << "match string:\t\t" << sm.str(0) << endl;
for (int i = 1; i < sm.size(); ++i)
{
s = sm.str(i);//捕获的字符串
cout << "index:" << i << "\t\t" << s << endl;
}
cout << endl;
}

void Print(sregex_iterator& pos)
{
string s;
sregex_iterator end;

if (pos == end)
return;

for (; pos != end; ++pos)
{
int size = pos->size();
//显示匹配的字符串
cout << "match string:\t\t" << pos->str(0) << endl;
for (int i = 1; i < size; ++i)
{
s = pos->str(i);//捕获的字符串
cout << "index:" << i << "\t\t" << s << endl;
}
}
cout << endl;
}

//测试函数
void Test1()
{
string text;
regex reg;

text = "<name>\n<first>111111111111111111111111111111111111111111111111111</first>\n<second>2</second>\n</name>\n";
reg = "<(.*)>(.*)</\\1>";

time_t tm1, tm2;

tm1 = time(NULL);
for (int i = 0; i < 10000; ++i)
{
sregex_iterator pos(text.cbegin(), text.cend(), reg);
Print(pos);
}
tm2 = time(NULL);
cout << "Test1:\t" << tm2 - tm1 << endl;
}

void Test2()
{
string text;
regex reg;

text = "<name>\n<first>111111111111111111111111111111111111111111111111111</first>\n<second>2</second>\n</name>\n";
reg = "<(.*?)>(.*?)</\\1>";

time_t tm1, tm2;

tm1 = time(NULL);
for (int i = 0; i < 10000; ++i)
{
sregex_iterator pos(text.cbegin(), text.cend(), reg);
Print(pos);
}
tm2 = time(NULL);
cout << "Test2:\t" << tm2 - tm1 << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
string text;
regex reg;
smatch sm;
bool bRet = false;

//////////////////////////////////////////////////////////////////////////
//"(.*?)"匹配从'"'字符开始,任意个非'\n'字符并以'"'结尾的字符串
//?表示非贪心模式,贪心模式会匹配到最长"name"="123",而非贪心则匹配最短"name"
//////////////////////////////////////////////////////////////////////////
text = "\"name\"=\"123\"\"";
reg = "\"(.*?)\"";
bRet = regex_search(text, sm, reg);
if (bRet)
Print(sm);

//////////////////////////////////////////////////////////////////////////
//<(.*)>(.*)</\1>表示匹配<A>...</A>这样的字符串
//<(.*)>(.*)</(.*)>表示匹配<A>...</B>这样的字符串,A和B可以相等也可以不相等
//\1表示该处的字符串和第一个捕获的字符串一样
//////////////////////////////////////////////////////////////////////////
text = "<name>\n<first>1</first>\n<second>2</second>\n</name>\n";
reg = "<(.*?)>(.*?)</\\1>";
bRet = regex_search(text, sm, reg);
if (bRet)
Print(sm);
sregex_iterator pos8(text.cbegin(), text.cend(), reg);
Print(pos8);

//////////////////////////////////////////////////////////////////////////
//(\d+)\?(\d+)
//(\d+)表示匹配一个或多个数字字符
//\?表示字符'?',与regex特殊字符冲突需要加'\'
//////////////////////////////////////////////////////////////////////////
text = "123?456";
reg = "(\\d+)\\?(\\d+)";
bRet = regex_match(text, sm, reg);
if (bRet)
Print(sm);

//////////////////////////////////////////////////////////////////////////
//"(?:[^"]+)":"([^"]+)"
//(?:[^"]+)表示匹配[^"]+,但是不获取匹配结果
//////////////////////////////////////////////////////////////////////////
text = "\"name\":\"123\",\"name\":\"456\",\"name\",\"789\"";
reg = "\"(?:[^\"]+)\":\"([^\"]+)\"";
sregex_iterator pos1(text.cbegin(), text.cend(), reg);
Print(pos1);


//////////////////////////////////////////////////////////////////////////
//"([mnop]{5})(.*)"
//([mnop]{5})表示匹配字符集('m','n','o','p')中的5个字符
//////////////////////////////////////////////////////////////////////////
text = "mnopmmnQrstuvwxyz";
reg = "([mnop]{5})(.*)";
bRet = regex_match(text, sm, reg);
if (bRet)
Print(sm);

//捕获qq邮箱中的qq号码
text = "123456@qq.com";
reg = "([0-9A-Za-z]+)@(?:[A-Za-z]+)\\.com";
bRet = regex_match(text, sm, reg);//123456
if (bRet)
Print(sm);

//////////////////////////////////////////////////////////////////////////
//"[^z]+z(.*)"
//[^z]+表示匹配非字符'z'一个或多个字符
//(.*)表示匹配任意字符
//////////////////////////////////////////////////////////////////////////
text = "abcedfz123456";
reg = "[^z]+z(.*)";
bRet = regex_match(text, sm, reg);//123456
Print(sm);

//////////////////////////////////////////////////////////////////////////
//"<(\S*?).*?>(.*?)</\1>"
//<(\S*?)表示从字符'<'开始匹配非空白字符0或多个,非贪婪模式,并存储匹配结果(A)
//.*?>表示匹配任意字符0个或多个,直到字符'>'为止,非贪婪模式,否则将匹配到最后一个为'>'的字符
//</\1>表示匹配字符串"</"开始接着匹配A(第一个匹配的结果)字符并以字符'>'结尾
//////////////////////////////////////////////////////////////////////////
text = "<html show=\"1\">hello</html>"
"<html>123</html>";
reg = "<(\\S*?).*?>(.*?)</\\1>";
sregex_iterator pos2(text.cbegin(), text.cend(), reg);
Print(pos2);

text = "<preson visible=\"1\">"
"<name>aa</name>"
"<age>18</age>"
"<sex>女</sex>"
"</preson>"
"<preson visible=\"1\">"
"<name>bb</name>"
"<age>20</age>"
"<sex>男</sex>"
"</preson>";
reg = "<(\\S*?).*?>"//匹配<person >
"<(\\S*?)>(.*?)</\\2>"//匹配<name></name>
"<(\\S*?)>(.*?)</\\4>"//匹配<age></age>
"<(\\S*?)>(.*?)</\\6>"//匹配<sex></sex>
"</\\1>";//匹配</person>
sregex_iterator pos3(text.cbegin(), text.cend(), reg);
Print(pos3);

//将字符串"colour"替换为"color"
text = "colour,colours,color,colourize";
reg = "(colo)(u)(r)";
string rep = "$1$3";//去除掉$2即字符'u'
string out = regex_replace(text, reg, rep);

//将字符串"<A>B</A>"替换为字符串"<A value="B" />"
text = "<person>\n"
"<first>Nico</first>\n"
"<last>Josuttis</last>\n"
"</preson>\n";
reg = "<(.*)>(.*)</\\1>";
rep = "<$1 value=\"$2\"/>";
out = regex_replace(text, reg, rep);

//测试两个正则表达式的效率
Test1();
Test2();

return 0;
}