參考:https://blog.csdn.net/l357630798/article/details/78235307
一、簡介:
本文主要是大致的介紹如何使用 C++ 標准庫中 std::regex 相關類庫,用來打發下無聊的時間。
在使用 C++ 標准庫正則表達式之前,肯定是要先學習正則表達式語法的,不解釋。
要學習正則表達式語法,你百度一下,可以百度一把大。但是,我個人覺得寫的最經典的莫過於這篇文章了 正則表達式30分鍾入門教程 ,感謝這篇文章作者 30 秒。我覺得只需要讀懂這篇文章的 80%,你將感受到正則表達式處理字符串那毀天滅地的威力。
二、常用 C++ 標准庫正則表達式類:
C++ 標准庫中常用正則表達式類主要包含如下 5 組:
有了以上 5 組模板,基本上可以處理所有的字符串處理需求了。
三、C++ 正則表達式模板的使用:
std::regex_match: 正則表達式需要匹配整個字符串序列,也就是說正則表達式要與字符串完全匹配。因此,它是單次匹配,否則匹配失敗。
范例代碼如下:
-
void match()
-
{
-
/
-
//std::regex_match
-
//std::regex_match: 正則表達式需要匹配整個字符串序列, 也就是說正則表達式要與
-
//字符串完全匹配, 因此, 它是單次匹配, 否則匹配失敗.
-
//此外, 它還可以獲取子匹配的組
-
-
std:: string text = "Date:2017-10-10";
-
-
//構造正則表達式
-
//這里 "()" 用於捕獲組, 捕獲組的編號是按照 "(" 出現的順序, 從左到右, 從1開始進行編號的
-
std:: string pattern = "Date.(\\d{4})-(\\d{2}-(\\d{2}))";
-
std::regex express(pattern);
-
-
//匹配
-
std:: cout.setf( std::ios_base::boolalpha);
-
/*模板函數1-1*/
-
//第0組一般是整個正則表達式匹配結果, 其他依次是捕獲組的結果
-
//這里使用的是 std::string::iterator 迭代器, 與 begin()/ end() 返回的迭代器類型(std::string::iterator)要一致
-
std::match_results< std:: string::iterator> results1;
-
if( std::regex_match(text.begin(), text.end(), results1, express))
-
{
-
std::match_results< std:: string::iterator>::const_iterator iter;
-
for (iter = results1.begin(); iter != results1.end(); iter++)
-
{
-
std:: cout << iter->length() << ": " << iter->str() << std:: endl;
-
}
-
}
-
/*輸出
-
15: Date:2017-10-10
-
4: 2017
-
5: 10-10
-
2: 10
-
*/
-
-
/*模板函數1-2*/
-
//第0組一般是整個正則表達式匹配結果, 其他依次是捕獲組的結果
-
//std::smatch == std::match_results<std::string::const_iterator>
-
std::smatch s_results1;
-
if( std::regex_match(text.cbegin(), text.cend(), s_results1, express))
-
{
-
std::match_results< std:: string::const_iterator>::const_iterator iter;
-
for (iter = s_results1.begin(); iter != s_results1.end(); iter++)
-
{
-
std:: cout << iter->length() << ": " << iter->str() << std:: endl;
-
}
-
}
-
/*輸出
-
15: Date:2017-10-10
-
4: 2017
-
5: 10-10
-
2: 10
-
*/
-
-
/*模板函數2*/
-
//顯示字符串是否符合正則表達式, 用於檢測字符串規則
-
std:: cout << std::regex_match(text.begin(), text.end(), express) << std:: endl;
-
-
/*模板函數3*/
-
//第0組一般是整個正則表達式匹配結果, 其他依次是捕獲組的結果
-
//std::cmatch == std::match_results<const char*>
-
std::cmatch c_results3;
-
if( std::regex_match(text.c_str(), c_results3, express))
-
{
-
for ( auto iter = c_results3.begin(); iter != c_results3.end(); iter++)
-
{
-
std:: cout << iter->length() << ": " << iter->str() << std:: endl;
-
}
-
}
-
/*輸出
-
15: Date:2017-10-10
-
4: 2017
-
5: 10-10
-
2: 10
-
*/
-
-
/*模板函數4*/
-
//顯示字符串是否符合正則表達式, 用於檢測字符串規則
-
std:: cout << std::regex_match(text.c_str(), express) << std:: endl;
-
-
/*模板函數5*/
-
//第0組一般是整個正則表達式匹配結果, 其他依次是捕獲組的結果
-
std::match_results< std:: string::const_iterator> s_results5;
-
if( std::regex_match(text, s_results5, express))
-
{
-
for ( size_t index = 0; index < s_results5.size(); index++)
-
{
-
//sub_match: 子匹配, match_results里面都存放的是sub_match
-
//sub_match 可以理解為 std::pair 的擴展, 它繼承了 std::pair,
-
//其中 first 實際上存放的是獲取的字符串頭指針地址, second 為尾指針地址
-
std::ssub_match sub = s_results5[index];
-
std:: cout << sub.length() << ": " << sub.str() << std:: endl;
-
}
-
}
-
/*輸出
-
15: Date:2017-10-10
-
4: 2017
-
5: 10-10
-
2: 10
-
*/
-
-
/*模板函數6*/
-
//顯示字符串是否符合正則表達式, 用於檢測字符串規則
-
std:: cout << std::regex_match(text, express) << std:: endl;
-
/
-
}
std::regex_search: 搜素正則表達式參數,但它不要求整個字符序列完全匹配。而且它只進行單次搜索,搜索到即停止繼續搜索,不進行重復多次搜索。
范例代碼如下:
-
void search()
-
{
-
/
-
//std::regex_search
-
//std::regex_search: 搜素正則表達式參數, 但它不要求整個字符序列完全匹配.
-
//而且它只進行單次搜索, 搜索到即停止繼續搜索, 不進行重復多次搜索.
-
-
std:: string text = "Date:2017-10-10 ~ 2017-10-15";
-
-
//構造正則表達式
-
//這里 "()" 用於捕獲組, 捕獲組的編號是按照 "(" 出現的順序, 從左到右, 從1開始進行編號的
-
std:: string pattern = "(\\d{4})-(\\d{2}-(\\d{2}))";
-
std::regex express(pattern);
-
-
//匹配
-
std:: cout.setf( std::ios_base::boolalpha);
-
-
/*模板函數1*/
-
//第0組一般是整個正則表達式匹配結果, 其他依次是捕獲組的結果, 它不進行重復多次搜索
-
std::match_results< std:: string::iterator> results1;
-
if( std::regex_search(text.begin(), text.end(), results1, express))
-
{
-
//使用迭代器遍歷, 這里的迭代器實際上是指向 std::sub_match 的指針
-
std::match_results< std:: string::iterator>::const_iterator iter;
-
for (iter = results1.begin(); iter != results1.end(); iter++)
-
{
-
std:: cout << iter->length() << ": " << iter->str() << std:: endl;
-
}
-
}
-
/*輸出
-
10: 2017-10-10
-
4: 2017
-
5: 10-10
-
2: 10
-
*/
-
-
/*模板函數2*/
-
//顯示是否有搜索到符合正則表達式的結果
-
std:: cout << std::regex_search(text.begin(), text.end(), express) << std:: endl;
-
-
/*模板函數3*/
-
//第0組一般是整個正則表達式匹配結果, 其他依次是捕獲組的結果, 它不進行重復多次搜索
-
std::cmatch c_results3;
-
if( std::regex_search(text.c_str(), c_results3, express))
-
{
-
for ( size_t index = 0; index < c_results3.size(); index++)
-
{
-
//獲取組里面的數據, 注意: 這里使用的是 std::csub_match,
-
//實際上存放在 std::match_results 里面的數據就是一組 std::sub_match
-
std::csub_match sub = c_results3[index];
-
-
//先獲取長度, 再獲取內容
-
std:: cout << sub.length() << ": " << sub.str() << std:: endl;
-
}
-
}
-
/*輸出
-
10: 2017-10-10
-
4: 2017
-
5: 10-10
-
2: 10
-
*/
-
-
/*模板函數4*/
-
//顯示是否有搜索到符合正則表達式的結果
-
std:: cout << std::regex_search(text.c_str(), express) << std:: endl;
-
-
/*模板函數5*/
-
//第0組一般是整個正則表達式匹配結果, 其他依次是捕獲組的結果, 它不進行重復多次搜索
-
std::smatch s_results5;
-
if ( std::regex_search(text, s_results5, express))
-
{
-
for ( auto iter = s_results5.begin(); iter != s_results5.end(); iter++)
-
{
-
std:: cout << iter->length() << ": " << iter->str() << std:: endl;
-
}
-
}
-
/*輸出
-
10: 2017-10-10
-
4: 2017
-
5: 10-10
-
2: 10
-
*/
-
-
/*模板函數6*/
-
//顯示是否有搜索到符合正則表達式的結果
-
std:: cout << std::regex_search(text, express) << std:: endl;
-
}
std::regex_replace: 多次搜索整個正則表達式(不考慮捕獲組),然后替換正則表達式匹配到的結果。
范例代碼如下:
-
void replace()
-
{
-
/
-
//std::regex_replace
-
//std::regex_replace:
-
-
std:: string text = "Date:2017-10-10 ~ 2017-10-15";
-
-
//構造正則表達式
-
//這里 "()" 用於捕獲組, 捕獲組的編號是按照 "(" 出現的順序, 從左到右, 從1開始進行編號的
-
std:: string pattern = "(\\d{4})-(\\d{2}-(\\d{2}))";
-
std::regex express(pattern);
-
-
//定義存儲結果變量已經替換字符
-
std::string result(256, '0');
-
std:: string substitutes = "2017-10-12";
-
-
/*模板函數1*/
-
//多次搜索整個正則表達式(不考慮捕獲組), 然后替換正則表達式匹配到的結果
-
//std::regex_replace 模板函數返回值實際上是新的字符串存入變量后尾部的指針位置, 置 0 是為了防止變量數據出錯或亂碼
-
* std::regex_replace(result.begin(), text.begin(), text.end(), express, substitutes) = '\0';
-
std:: cout << result.c_str() << std:: endl;
-
/*輸出:
-
Date:2017-10-12 ~ 2017-10-12
-
*/
-
-
result.clear();
-
result.resize( 256, '0');
-
-
/*模板函數2*/
-
//多次搜索整個正則表達式(不考慮捕獲組), 然后替換正則表達式匹配到的結果
-
//std::regex_replace 模板函數返回值實際上是新的字符串存入變量后尾部的指針位置, 置 0 是為了防止變量數據出錯或亂碼
-
result = std::regex_replace(text, express, substitutes);
-
std:: cout << result.c_str() << std:: endl;
-
/*輸出:
-
Date:2017-10-12 ~ 2017-10-12
-
*/
-
}
std::regex_iterator: 用於多次重復匹配,不分組,只進行多次匹配整個正則表達式,可獲取整個正則表達式的結果。
范例代碼如下:
-
void iterator()
-
{
-
/
-
//std::regex_iterator
-
//std::regex_iterator: 用於多次重復匹配, 不分組, 只進行多次匹配整個正則表達式,
-
//可獲取整個正則表達式的結果
-
-
std:: string text = "Date:2017-10-10 ~ 2017-10-15";
-
-
//構造正則表達式
-
//這里 "()" 用於捕獲組, 捕獲組的編號是按照 "(" 出現的順序, 從左到右, 從1開始進行編號的
-
std:: string pattern = "(\\d{4})-(\\d{2}-(\\d{2}))";
-
std::regex express(pattern);
-
-
std::regex_iterator<std::string::const_iterator> begin(text.cbegin(), text.cend(), express);
-
//std::sregex_iterator == std::regex_iterator<std::string::const_iterator>
-
for ( auto iter = begin; iter != std::sregex_iterator(); iter++)
-
{
-
std:: cout << iter->length() << ": " << iter->str() << std:: endl;
-
}
-
/*輸出
-
10: 2017-10-10
-
10: 2017-10-15
-
*/
-
}
std::regex_token_iterator: 用於多次匹配正則表達式, 它可以獲取整個正則表達式的結果,也可以獲取正則表達式的前綴,還可以獲取正則表達式的分組子匹配。
范例代碼如下:
-
void token_iterator()
-
{
-
/
-
//std::regex_token_iterator
-
//std::regex_token_iterator: 用於多次匹配正則表達式, 它可以獲取整個正則表達式
-
//的結果, 也可以獲取正則表達式的前綴, 還可以獲取正則表達式的分組子匹配
-
-
std:: string text = "Date:2017-10-10 ~ 2017-10-15";
-
-
//構造正則表達式
-
//這里 "()" 用於捕獲組, 捕獲組的編號是按照 "(" 出現的順序, 從左到右, 從1開始進行編號的
-
std:: string pattern = "(\\d{4})-(\\d{2}-(\\d{2}))";
-
std::regex express(pattern);
-
-
/*構造函數2-1*/
-
//(多次匹配)顯示正則表達式匹配, 即參數 4 等於 0
-
std::regex_token_iterator<std::string::const_iterator> begin2_1(text.cbegin(), text.cend(), express);
-
//std::sregex_token_iterator == std::regex_token_iterator<std::string::const_iterator>
-
for ( auto iter = begin2_1; iter != std::sregex_token_iterator(); iter++)
-
{
-
std:: cout << iter->length() << ": " << iter->str() << std:: endl;
-
}
-
/*輸出
-
10: 2017-10-10
-
10: 2017-10-15
-
*/
-
-
/*構造函數2-2*/
-
//(多次匹配)顯示正則表達式匹配到的前綴, -1 則表示只顯示前綴
-
std::regex_token_iterator<std::string::const_iterator> begin2_2(text.cbegin(), text.cend(), express, -1);
-
for ( auto iter = begin2_2; iter != std::sregex_token_iterator(); iter++)
-
{
-
std:: cout << iter->length() << ": " << iter->str() << std:: endl;
-
}
-
/*輸出
-
5: Date:
-
3: ~
-
*/
-
-
/*構造函數2-3*/
-
//(多次匹配)顯示正則表達式子匹配, 3 表示第三組子匹配
-
std::regex_token_iterator<std::string::const_iterator> begin2_3(text.cbegin(), text.cend(), express, 3);
-
for ( auto iter = begin2_3; iter != std::sregex_token_iterator(); iter++)
-
{
-
std:: cout << iter->length() << ": " << iter->str() << std:: endl;
-
}
-
/*輸出
-
2: 10
-
2: 15
-
*/
-
-
/*構造函數3*/
-
//(多次匹配)顯示正則表達式匹配到的前綴和子匹配, -1 表示前綴, 2 表示第二個子匹配
-
std:: vector< int> vec;
-
vec.push_back( -1);
-
vec.push_back( 2);
-
std::regex_token_iterator<std::string::iterator> begin3(text.begin(), text.end(), express, vec);
-
for ( auto iter = begin3; iter != std::regex_token_iterator< std:: string::iterator>(); iter++)
-
{
-
std:: cout << iter->length() << ": " << iter->str() << std:: endl;
-
}
-
/*輸出
-
5: Date:
-
5: 10-10
-
3: ~
-
5: 10-15
-
*/
-
-
/*構造函數4*/
-
//(多次匹配)顯示正則表達式匹配到的前綴和整個正則表達式匹配, -1 表示前綴, 0 表示匹配整個正則表達式.
-
int arr[] = { -1, 0};
-
std::regex_token_iterator<std::string::iterator> begin4(text.begin(), text.end(), express, arr);
-
for ( auto iter = begin4; iter != std::regex_token_iterator< std:: string::iterator>(); iter++)
-
{
-
std:: cout << iter->length() << ": " << iter->str() << std:: endl;
-
}
-
/*輸出
-
5: Date:
-
10: 2017-10-10
-
3: ~
-
10: 2017-10-15
-
*/
-
}
主函數:
-
int main()
-
{
-
search();
-
-
system( "pause");
-
return 0;
-
}
以上范例及說明基本上已介紹模板的使用方法,其中模板中的 match_flag_type 我沒有使用,可以查閱 MSDN 來使用。另,源代碼下載地址:std::regex usge demo