C++正则表达式
2015-08-24 00:38 rangers 阅读(5220) 评论(0) 编辑 收藏 举报正则表达式是处理文本强有力的工具,它使用一套复杂且完善的语法规则,能够解决文本处理领域的绝大多数问题,诸如验证、匹配、查找、替换等等,而这些问题用通常的字符串算法是很难解决的。
C++11正式加入了regex库,下面通过几个简单的例子介绍一下regex
库的使用。
有关正则表达式的语法知识,参考这里。
要使用regex库,要包含头文件#include <regex>
类摘要
basic_regex
template<class _Elem,
class _RxTraits = regex_traits<_Elem> >
class basic_regex
: public _Regex_base
{ //
...
typedef basic_regex<char> regex;
typedef basic_regex<wchar_t> wregex;
该类封装了正则表达式的解析和编译,是正则表达式的基本类。一般有两种特化regex
和wregex
分别对应窄字符和宽字符。
构造一个正则表达式很简单:
string regex_str("^(\\d{6})((1|2)\\d{3})((0|1)\\d)([0-3]\\d)(\\d{3}(X|\\d))$");
std::regex pattern(regex_str,std::regex::icase);
match_results
该类保存了正则表达式匹配的结果。match_results
为正则表达式的匹配结果提供了一个类似容器的视图,可以用size()和empty()判断匹配结果中子表达式的数量,operator[]返回低i个子表达式。如果i==0,则返回整个表达式的匹配对象。
match_results
有以下特化方式:
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;
sub_match
该模板类是一个类似迭代器的对象,继承自std::pair
,用来表示一个与子表达式匹配的序列,可以把它当作一个字符区间。
正则匹配
自由函数regex_match()
用来检查一个字符串是否完全匹配一个正则表达式,返回bool结果。
//匹配身份证号码
// ^\d{6}(1|2)\d{3}(0|1)\d[0-3]\d\d{3}(X|\d)$
string regex_str("^(\\d{6})((1|2)\\d{3})((0|1)\\d)([0-3]\\d)(\\d{3}(X|\\d))$");
std::regex pattern(regex_str,std::regex::icase);//忽略字母大小写
string id("61251719901212444X");
assert(std::regex_match(id,pattern) == true);
// [a-zA-Z0-9_-]+@[a-zA-Z0-9]+\.[a-zA-Z0-9]+ 邮箱简单正则
string mail_reg_str("^[a-zA-Z0-9_-]+@[a-zA-Z0-9]+\\.[a-zA-Z0-9]+$");
std::regex mail_reg(mail_reg_str,std::regex::icase);
assert(std::regex_match("chm--1989@163.com",mail_reg) == true);
使用正则匹配结果
使用match_results
来提取匹配结果。
void IPTest()
{
//识别一个IP地址,并打印各个部分
//输入exit退出程序
bool isInputEnd = false;
//(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})
//有四个子表达式,括号中的内容为一个子表达式
std::regex ip_reg("(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})");
std::smatch matchResult;
const string exitStr("EXIT");
while (!isInputEnd)
{
cout << "\nInput a IP address:";
string inputStr;
std::getline(std::cin,inputStr);
if (inputStr.empty())
{
continue;
}
string tmpStr(inputStr);
std::transform(tmpStr.begin(),tmpStr.end(),tmpStr.begin(),toupper);
if (tmpStr == exitStr)
{
cout << "\nSYSTEM EXIT!";
isInputEnd = true;
continue;
}
//正则匹配
if (std::regex_match(inputStr,matchResult,ip_reg))
{
cout << "Match: ";
//打印子表达式结果
for (size_t i = 1; i < matchResult.size(); ++i)
{
cout << matchResult[i] << " ";
}
}
else
{
cout << "Not Match!";
}
}
}
运行如下:
正则查找
regex_search()
与 regex_match
的区别是:regex_match
要求输入的字符串必须要与正则表达式完全匹配,而regex_search
则检测输入表达式中是否包含正则表达式,即存在一个匹配正则表达式的子串。
//搜索输入字符串中所有满足正则表达式 \d{3} 的子串
std::regex reg2("\\d{3}");
string test_str("abc12312a--1b234-7890abc567");
string::const_iterator iter = test_str.begin();
string::const_iterator iterEnd = test_str.end();
std::smatch match_result;
cout << "\n\n" << test_str;
while (std::regex_search(iter,iterEnd,match_result,reg2))
{
cout << "\nMatch: " << match_result[0];
iter = match_result[0].second; //更新搜索起始位置
}
正则替换
regex_repalce
template<class _RxTraits,
class _Elem>
_STD basic_string<_Elem> regex_replace(
const _STD basic_string<_Elem>& _Str,
const basic_regex<_Elem, _RxTraits>& _Re,
const _STD basic_string<_Elem>& _Fmt,
regex_constants::match_flag_type _Flgs =
regex_constants::match_default)
{ // search and replace
...
regex_replace 在整个字符序列中查找正则表达式e的所有匹配。这个算法每次成功匹配后,就根据参数fmt对匹配字符串进行格式化。
//使用regex_replace 实现trim功能,去掉字符串前后的空白字符
std::regex reg1("^(\\s)*");
std::regex reg2("\\s*$");
string test_str(" abc \t");
string t("");
test_str = std::regex_replace(test_str,reg1,t); //trim_left
test_str = std::regex_replace(test_str,reg2,t); //trim_right
测试结果如下: