首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C++ 正則表達式提取日誌錯誤修正指南

     編輯:程式設計綜合問答

問題現象

嘗試用 `std::regex` 從字串 20110604-092737<INFO :0xb7f2a6d0>: Player logout: ... 中提取前綴時間戳與日誌等級部分,但原寫法 "^[\\d\\-\\d\\<\\w\\s{0,1}\\:\\w>]" 編譯通過卻無法匹配,且在 VC2010 下報錯。

錯誤分析

  • 字元類別濫用:`[\\d\\-\\d...]` 將 `-` 視為字面字元而非範圍運算子,且重複寫入 `\\d`。
  • 轉義混淆:`<` `>` `:` 在字元類別中無需轉義,但在正則整體中 `<` 需轉義為 `\\<`(視引擎而定),C++ 字串字面值又需雙重轉義 `\\\\<`。
  • 量詞錯位:`\\s{0,1}` 寫在字元類別內部無效,應放在外部修飾 `\\w`。

正確寫法(經測試可行)

// 使用原始字串字面值 (C++11) 避免雙重轉義地獄
std::regex rgx(R"(^\d+-\d+<\w+\s?:\w+>)");

// 傳統寫法(雙重轉義)
std::regex rgx("^\\d+-\\d+<\\w+\\s?:\\w+>");

關鍵點解析

  1. `^` 鎖定行首。
  2. `\\d+` 匹配一位以上數字(日期與時間部分)。
  3. `-` 字面連字號。
  4. `<` `>` 匹配尖括號(標準正則中 `<` `>` 為字面字元,無需轉義;若引擎視為單詞邊界則需 `\\<` `\\>`)。
  5. `\\w+` 匹配單詞字元(INFO)。
  6. `\\s?` 可選空白(冒號前可能有空格)。
  7. `:` 字面冒號。
  8. `\\w+` 匹配十六進位位址中的字母數字部分(注意:`0x` 開頭含 `x`,`\\w` 剛好涵蓋)。

完整驗證程式

#include <regex>
#include <iostream>
#include <string>

int main() {
    std::string log = "20110604-092737<INFO :0xb7f2a6d0>: Player logout: 忘了愛過誰";
    std::regex rgx(R"(^\d+-\d+<\w+\s?:\w+>)"); // C++11 raw string
    
    std::smatch m;
    if (std::regex_search(log, m, rgx)) {
        std::cout << "匹配成功: " << m.str() << '\n';
        // 輸出: 20110604-092737<INFO :0xb7f2a6d0>
    } else {
        std::cout << "匹配失敗\n";
    }
    return 0;
}

避坑建議

  • 優先使用 C++11 原始字串字面值 `R\"(...)\"` 編寫正則,極大降低轉義負擔。
  • 在 regex101 等工具先行測試正則邏輯,再移植至代碼。
  • C++ `` 性能一般,高頻呼叫場景建議改用 boost::regex 或 re2。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved