1. 程式人生 > >C++Primer_Chap17_標準庫特殊設施_List03_正則表示式_筆記

C++Primer_Chap17_標準庫特殊設施_List03_正則表示式_筆記

  正則表示式(regular expression)是一種描述字元序列的方法,是一種及其強大的計算工具。C++正則表示式庫(RE庫)定義在標頭檔案regex中,包含多個元件:

正則表示式庫元件
regex 表示有一個正則表示式的類,即regex類表示一個正則表示式
regex_match 將一個字元序列與一個正則表示式匹配
regex_search 尋求第一個與正則表示式匹配的子序列
regex_replace 使用給定格式替換一個正則表示式
sregex_iterator 迭代器介面卡,呼叫regex_search來遍歷一個string中所有匹配的子串
smatch 容器類,儲存在string中搜索的結果
ssub_match string中匹配的子表示式的結果

  

regex_search和regex_match的引數
注意:這些操作返回bool值,指出是否找到匹配

(seq, m, r, mft)

 

(seq, r, mft )

在字元序列seq中查詢regex物件r中的正則表示式。seq可以是一個string、表示範圍的一對迭代器以及一個指向空字元結尾的字元陣列的指標

 

m是一個match物件,用來儲存匹配結果的細節。m和seq必須具有相容的型別

 

mft是一個可選的regex_constants::match_flag_type值。

使用正則表示式庫

  查詢違反拼寫規則“i除非在c之後,否則必須在e之前”的單詞示例:

//查詢不在字元c之後的字串ei
string pattern("[^c]ei");

pattern = "[[:alpha:]]" + pattern + "[[:alpha:]]*";
regex r(pattern);    //構造一個用於查詢模式的regex
smatch results;

string test_str = "receipt freind theif receive";

if( regex_search(text_str, results, r))
     cout << results.str() << endl;

  我們首先定義了一個string來儲存希望查詢的正則表示式。正則表示式[^c]表明我們希望匹配任一不是'c'的字元,而[^c]ei指出我們想要匹配這種字元後接ie的字串。此模式描述的字串恰好包含三個字元。我們想要包含此模式的單詞的完整內容。為了與整個單詞匹配,我們還需要一個正則表示式與這個三字母模式之前和之後的字母匹配。

  這個正則表示式包含0個或多個字母后接我們的三字母的模式,然後再接0個或多個額外的字母。預設情況下,regex使用的正則表示式語言是ECMAScript。在ECMAScript中,模式[[:alpha:]]匹配任一字母,符號+和*分別表示我們希望“1個或多個”或“0個或多個”匹配。因此[[::alpha:]]*將匹配0個或多個字母。

指定regex物件的選項

  當我們定義一個regex或是對一個regex呼叫assign為其賦予新值時,可以指定一些標誌來影響regex如何操作。這些標誌控制regex物件的處理過程。對於指出編寫正則表示式所用語言的6個標誌,我們必須設定其中一個,且只能設定一個。預設情況下,ECMAScript標誌被設定,從而regex會使用ECMA-262規範,這也是很多Web瀏覽器所用的正則表示式語言。

regex和wregex選項

regex r(re)

regex r(re, f)

re表示一個正則表示式,它可以是一個string、一個表示字元範圍的迭代對、一個指向空字元結尾的字元陣列的指標、一個字元指標和一個計數器或是一個花括號包圍的字元列表。

f是指出物件如何處理的標誌。f通過下面列出的值來設定。如果未指定f,預設值為ECMAScript。

r1 = re

將r1中的正則表示式替換成re。

re表示一個正則表示式,它可以是另一個regex物件、一個string、一個指向空字元結尾的字元陣列的指標或是一個花括號包圍的字元列表。

r1.assign(re, f) 與使用賦值運算子(=)效果相同
r.mark_count() r中子表示式的數目
r.flags() 返回r的標誌集
注:建構函式和賦值操作也可能丟擲型別為regex_error的異常。
定義regex時指定的標誌
定義在regex和regex_constants::synatax_option_type中
icase 在匹配過程中忽略大小寫
nosubs 不儲存匹配的子表示式
optimize 執行速度優先於構造速度
ECMAScript 使用ECMA-262指定的語法
basic 使用POSIX基本的正則表示式語法
extended 使用POSIX擴充套件的正則表示式語法
awk 使用POSIX版本的awk語言的語法
grep 使用POSIX版本的grep的語法
egrep

使用POSIX版本的egrep的語法

  一個正則表示式來識別副檔名的示例:

//1個或多個字母或數字字元後面接一個'.'再接"cpp"或"cxx"或"cc"
regex r("[[:alnum:]]+\\.{cpp|cxx|cc}$", regex::icase);
smatch results;
string filename;
while( cin >> filename)
    if( regex_search(filename, results, r))
        cout << results.str() << endl;

  在正則表示式語言中,字元點(.)通常匹配任意字元。與C++一樣,可以在字元之前放置一個反斜線\來去掉其特殊含義。由於反斜線\也是C++中的一個特殊字元,我們在字串常量中必須連續使用兩個反斜線。

  一個正則表示式的語法是否正確是在執行時解析的。如果我們編寫的正則表示式存在錯誤,則在執行時標準庫會丟擲一二型別為regex_error的異常。類似標準庫異常型別,regex_error有一個描述發生什麼錯誤的what操作,和一個返回錯誤型別對應的數值編碼的code成員。

try{
    regex r("[[:alnum:]+\\.(cpp|cxx|cc)$", regex::icase);
}catch (regex_error e)
{
    cout << e.what() << "\ncode:" << e.code() << endl;
}