C++正则表达式

时间:2021-04-28 05:57:02

环境: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;
}