正則表達式是處理文本強有力的工具,它使用一套復雜且完善的語法規則,能夠解決文本處理領域的絕大多數問題,諸如驗證、匹配、查找、替換等等,而這些問題用通常的字符串算法是很難解決的。
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
測試結果如下:

