C++實現簡單的日期正則表達式


  • 簡單的日期正則表達式

一個簡單的日期解析程序,從yyyy-mm-dd格式的日期字符串中,分別獲取年月日。

先設置一個簡單的正則表達式,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;
}

執行輸出:

0: 2018-7-12

smatch類型是一個匹配結果字符串列表,列表中第一個元素永遠是執行匹配操作的原始字符串,后續是根據表達式從原始字符串中解析出的子串。

程序輸出結果表示日期字符串與表達式匹配正確,但並沒有解析出各個日期字段子串。

如果需要解析出子串,則需要對表達式分組。

  • 表達式分組

分組后的表達式,匹配操作才會以分組位單位輸出解析出的子串。將pattern表達式修改如下:

regex  pattern("([0-9]{4}-[0-9]{1,2}-[0-9]{1,2})");

在這里,整個表達式包含在一個圓括號里,將整個表達式作為一個分組。

執行后輸出:

0: 2018-7-12
1: 2018-7-12

下標為1的輸出項,即為整個表達式分組所匹配到的內容,也就是整個日期字符串,但這還沒有達到逐字段分解的目標,需要將分組細分。

  • 表達式分組細分

將表達式改為:

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})");

在分組中加上 “?:” 前綴,即表示該分組位消極分組,在此表達式中,將數字月份和名稱月份的子分組都標記為消息分組,運行結果:

1: 2018
2: Jan
3: 18


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM