一 簡介
概括而言,使用正則表達式處理字符串的流程包括:用正則表達式定義要匹配的字符串的規則,然后對目標字符串進行匹配,最后對匹配到的結果進行操作。C++ 的 regex 庫提供了用於表示正則表達式和匹配結果的基本類型,以及使用這些基本類型作為參數或返回結果(通過參數來返回,不是函數的返回值)的搜尋、匹配、替換等函數。
二 基本類型
2.1 basic_regex
及其實例化類型 regex
、wregex
模板類型 basic_regex
用於表示正則表達式對象,<regex>
庫提供了它的兩種實例化類型:
typedef basic_regex<char> regex;
typedef basic_regex<wchar_t> wregex;
構造函數一般接受一個字符串作為參數,如
std::regex reg ("[0-9A-Z]+");
構造函數中還有一個默認參數flags,默認值為 std::regex::ECMAScript
,該參數可以用來設置正則表達式所采用的語法(有且只能設置一種),如 std::regex::grep, std::regex::awk
等,也可以設置 case insensitive,flags 的多個值用比特位 OR 操作|
連接,如
std::regex ninth ("\\bd\\w+", ECMAScript | icase );
具體的構造函數聲明及fags值的定義參考basic_regex::basic_regex - C++ Reference。
2.2 match_results
、sub_match
及其實例化類型
match_results
是一種 container-like 的模板類,用於存放對目標串執行完 regex matching 操作后匹配到的結果,其中的每個元素(即每個匹配結果)是一個 sub_match
的實例化對象。
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;
與 match_results
相似,sub_match
的實例化類型也有四種:
typedef sub_match<const char*> csub_match;
typedef sub_match<const wchar_t*> wcsub_match;
typedef sub_match<string::const_iterator> ssub_match;
typedef sub_match<wstring::const_iterator> wssub_match;
sub_match
對象存儲的不是匹配到的字符串本身,而是指向這個串開始(initial)和結束后一個字符(past-the-end)的 bidirectional iterators
,但是它們表現起來類似於一個字符串,成員函數 length
返回字符串長度。compare
用於和一個字符串或另一個 sub_match
對象比較,相等則返回0,不等則:若它比參數小(第一個未匹配的字符小於參數中該位置字符,或者它是參數的一個前綴)返回一個負值,否則返回一個正值。str
返回對應的字符串。
根據一次匹配的結果,match_results
可能為空也可能不空,使用 match_results::empty()
來判空,使用 match_results::size()
來獲取元素個數。對於一個不空的 match_results
對象,其第一個 sub_match
元素([0]
)對應着整個完整匹配,后續的元素對應着正則表達式中的 sub-match(即用()
括起來的各個分組匹配),未匹配的部分可以通過 prefix
和 suffix
來獲取。下面是一個簡單的例子,參考自 boost的文檔:
#include <regex>
#include <iostream>
#include <string>
int main() {
std::string target = "@abc def--";
std::regex e("(\\w+)\\W+(\\w+)");
std::smatch sm;
std::regex_search(target, sm, e);
std::cout << "sm.prefix: " << sm.prefix() << std::endl;
for (int i = 0; i < sm.size(); ++i) {
std::cout << "sm[" << i << "]: " << sm[i] << std::endl;
}
std::cout << "sm.prefix: " << sm.suffix() << std::endl;
return 0;
}
Output:
======================================
sm.prefix: @
sm[0]: abc def
sm[1]: abc
sm[2]: def
sm.prefix: --
三 正則操作
3.1 regex_match
用於將目標串和正則表達式匹配,返回一個 bool 值,true
為匹配,false
為不匹配。匹配的含義是目標字符串必須完全和正則表達式相匹配,不能有多余的字符,如果需要部分匹配則應使用regex_search
。函數簽名有很多,詳見cplusplus.com。構造函數分成兩種,一種接受一個 match_results
作為對象,參數順序為:待匹配的字符串,match_results
對象,正則表達式對象;另一種沒有 match_results
,參數順序為:待匹配的字符串,正則表達式對象。此外,函數還接受一個可選的 flags
參數,用於控制匹配選項,詳見鏈接。
3.2 regex_search
只要目標字串中有一個字串(無論該子串在字符串中什么位置)能和正則表達式相匹配就返回true
。函數簽名同regex_match
相似。
3.3 regex_replace
該函數有多個重載版本,常用的版本中參數順序基本上 s
,rgx
,fmt
,flags
,其中 s
為要處理的字符串,rgx
為要匹配的正則表達式,fmt
為要替換的字符串,其中可以包含格式化字符,下述,flags
為可選的參數,用於設置一些選項。
參數 fmt
中可以包含下列格式化字符:
characters | replacement |
---|---|
$n |
表示第n組匹配,n大於0 |
$& |
表示整個匹配 |
$` |
prefix |
$´ |
suffix |
$$ |
表示$ 這個字符本身 |
在替換時,會先將參數 fmt
中的格式化字符替換成相應的內容,然后再將這個字符串替換掉目標字符串中的完整匹配(相當於 $&
或 match_results[0]
)。