一個簡單的日期解析程序,從yyyy-mm-dd格式的日期字符串中,分別獲取年月日。ios
先設置一個簡單的正則表達式,4位數字的「年」,1-2位數字的「月」和一樣1-2位數字的「日」,中間‘-’做爲分隔符。程序代碼:正則表達式
#include <iostream> #include <regex> using namespace std; int main() { string text = "2018-7-12"; regex pattern("[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}"); smatch results; if ( regex_match(text, results, pattern) ) { smatch::iterator it = results.begin(); int i = 0; for(; it != results.end(); ++it, ++i) cout<<i<<": "<<*it<<endl; } else { cout << "match failed: " <<text<< endl; } return 0; }
執行輸出:spa
0: 2018-7-12
smatch類型是一個匹配結果字符串列表,列表中第一個元素永遠是執行匹配操做的原始字符串,後續是根據表達式從原始字符串中解析出的子串。code
程序輸出結果表示日期字符串與表達式匹配正確,但並無解析出各個日期字段子串。字符串
若是須要解析出子串,則須要對錶達式分組。string
分組後的表達式,匹配操做纔會以分組位單位輸出解析出的子串。將pattern表達式修改以下:it
regex pattern("([0-9]{4}-[0-9]{1,2}-[0-9]{1,2})");
在這裏,整個表達式包含在一個圓括號裏,將整個表達式做爲一個分組。io
執行後輸出:class
0: 2018-7-12 1: 2018-7-12
下標爲1的輸出項,即爲整個表達式分組所匹配到的內容,也就是整個日期字符串,但這尚未達到逐字段分解的目標,須要將分組細分。stream
將表達式改成:
regex pattern("([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})");
其中包含了3個分組(儘管後面兩個分組表達式同樣,但月份和日期的取值範圍並不徹底相同,這裏只簡單設置)
執行結果:
0: 2018-7-12 1: 2018 2: 7 3: 12
終於達到了日期字段分解的目標。
而後,日期字符串中,月份的表達方式能夠是數字,也能夠是字母名稱,如Jan,Feb,Mar等,那麼就須要在表達式中兼容多種格式的日期字符串。
當前日期字符串變動名稱月份,表達式中增長月份名稱:
string text = "2018-Jan-18"; regex pattern("([0-9]{4})-(([0-9]{1,2})|(Jan|Feb|Mar))-([0-9]{1,2})");
運行結果:
0: 2018-Jan-18 1: 2018 2: Jan 3: 4: Jan 5: 18
在這個表達式中,數字月份做爲一個分組,名稱月份也是一個分組,二者又合併成一個月份分組,所以匹配月份時,存在這三個分組(一個父分組包含2個子分組),運行輸出結果中2-4分別是這三個分組分別對月份匹配的結果,數字月份的子分組表達式沒有匹配到,所以輸出空字符串。
這樣的結果並不使人滿意,對於月份來講,只需輸出一項便可,即對於月份匹配,兩個子分組不須要單獨輸出,只須要表示月份的父級分組輸出便可。
經過將子分組指定爲消極分組(Passive Group)便可。
將表達式改成:
regex pattern("([0-9]{4})-((?:[0-9]{1,2})|(?:Jan|Feb|Mar))-([0-9]{1,2})");
在分組中加上「?:」前綴,即表示該分組位消極分組,在此表達式中,將數字月份和名稱月份的子分組都標記爲消息分組,運行結果:
0: 2018-Jan-18 1: 2018 2: Jan 3: 18