首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言正則表達式 (POSIX Regex) 完整指南:API 詳解與 Email 驗證實戰

     編輯:關於C語言

常用 C 正則庫對比

庫特點授權
GNU Regex (POSIX)系統內建、標準 API、功能基礎LGPL
PCRE / PCRE2Perl 相容、功能豐富、效能高BSD
Boost.RegexC++ 封裝、Header-only 可用Boost
RE2Google 開發、線性時間保證、無回溯BSD

本文以標準 <regex.h> (GNU Regex) 為例。

四大核心 API

1. regcomp - 編譯模式


int regcomp(regex_t *preg, const char *pattern, int cflags);
// 成功返回 0,失敗返回錯誤碼
// cflags: REG_EXTENDED (擴展語法), REG_ICASE (忽略大小寫), REG_NOSUB (不捕獲子串)

2. regexec - 執行匹配


int regexec(const regex_t *preg, const char *string,
            size_t nmatch, regmatch_t pmatch[], int eflags);
// 成功返回 0 (匹配),REG_NOMATCH (不匹配),其他錯誤碼
// nmatch/pmatch: 捕獲群組位置 (rm_so 起始, rm_eo 結束)

3. regerror - 錯誤訊息


size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);
// 將錯誤碼轉為人類可讀字串

4. regfree - 釋放資源


void regfree(regex_t *preg);
// 必須呼叫避免洩漏

完整範例:Email 格式驗證


#include 
#include 
#include 

int main() {
    regex_t reg;
    int reti;
    char msgbuf[100];

    // 編譯:擴展正則語法
    reti = regcomp(®, "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", REG_EXTENDED);
    if (reti) {
        regerror(reti, ®, msgbuf, sizeof(msgbuf));
        fprintf(stderr, "Regex compile failed: %s\n", msgbuf);
        return 1;
    }

    char email[256];
    while (1) {
        printf("Enter email: ");
        if (!fgets(email, sizeof(email), stdin)) break;
        email[strcspn(email, "\n")] = 0;  // 去除換行

        reti = regexec(®, email, 0, NULL, 0);
        if (!reti) {
            puts("Valid email");
        } else if (reti == REG_NOMATCH) {
            puts("Invalid email");
        } else {
            regerror(reti, ®, msgbuf, sizeof(msgbuf));
            fprintf(stderr, "Match error: %s\n", msgbuf);
        }
    }

    regfree(®);
    return 0;
}

POSIX 擴展正則語法重點

捕獲群組位置提取範例


regmatch_t pmatch[3];  // 0: 整體, 1: 第一群組, 2: 第二群組
reti = regexec(®, "user@example.com", 3, pmatch, 0);
if (!reti) {
    // 整體匹配
    for (int i = pmatch[0].rm_so; i < pmatch[0].rm_eo; i++) putchar(email[i]);
    puts("");
    // 第 1 群組 (用戶名)
    for (int i = pmatch[1].rm_so; i < pmatch[1].rm_eo; i++) putchar(email[i]);
    puts("");
}

常見陷阱與最佳實踐

  1. 雙重轉義:C 字串字面值中 \ 需寫為 \\,正則引擎再見到 \。如 \\. 匹配字面點號。
  2. 編譯一次,多次匹配:regcomp 開銷大,循環外編譯。
  3. 檢查 regcomp 回傳值:模式語法錯誤會導致編譯失敗。
  4. 必須 regfree:regex_t 內部動態分配記憶體。
  5. 執行緒安全:regex_t 非執行緒安全,多執行緒各自編譯或加鎖。
  6. 效能考量:複雜模式 (嵌套量詞) 可能導致災難性回溯,考慮 RE2 或限制輸入長度。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
元字元含義
.任意單一字元 (除換行)
[...]字元類別
[^...]反向字元類別
* + ? {m,n}量詞:0或多、1或多、0或1、m到n次
()捕獲群組
|或
^ $行首/行尾
\轉義