POSIX 正則表達式概述
GNU C 庫 (glibc) 提供 POSIX.2 標準的正則表達式接口,風格與 Perl/PCRE 不同,屬於**擴展正則表達式 (ERE)** 方言。頭文件 <regex.h>。
核心數據結構與函數
typedef struct {
regoff_t rm_so; // 匹配起始偏移
regoff_t rm_eo; // 匹配結束偏移 (不包含)
} regmatch_t;
int regcomp(regex_t *preg, const char *pattern, int cflags);
int regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
void regfree(regex_t *preg);
編譯標志 cflags
| 標志 | 含義 |
REG_EXTENDED | 使用擴展正則語法 (ERE),而非基本正則 (BRE)。**強烈建議始終開啟**。 |
REG_ICASE | 忽略大小寫匹配。 |
REG_NOSUB | 不記錄子表達式匹配位置,僅返回成功/失敗,加快速度。 |
REG_NEWLINE | . 不匹配換行符,^/$ 匹配行首/行尾(而非整串首尾)。 |
執行標志 eflags
| 標志 | 含義 |
REG_NOTBOL | ^ 不匹配字符串開頭(視為行中間)。 |
REG_NOTEOL | $ 不匹配字符串結尾。 |
完整使用流程示例
#include <stdio.h>
#include <regex.h>
#include <string.h>
int main() {
const char *pattern = "abc([0-9]+)"; // 捕獲組:數字序列
const char *input = "Abc1234";
regex_t regex;
regmatch_t matches[3]; // [0]整體匹配, [1]第一個捕獲組
int ret;
// 1. 編譯正則
ret = regcomp(®ex, pattern, REG_EXTENDED | REG_ICASE);
if (ret != 0) {
char errbuf[100];
regerror(ret, ®ex, errbuf, sizeof(errbuf));
fprintf(stderr, "編譯失敗: %s\n", errbuf);
return 1;
}
// 2. 執行匹配
ret = regexec(®ex, input, 3, matches, 0);
if (ret == REG_NOMATCH) {
printf("不匹配\n");
} else if (ret == 0) {
// 3. 提取匹配子串
char buf[100];
// 整體匹配
snprintf(buf, sizeof(buf), "%.*s",
(int)(matches[0].rm_eo - matches[0].rm_so),
input + matches[0].rm_so);
printf("整體匹配: [%s]\n", buf);
// 第一個捕獲組
snprintf(buf, sizeof(buf), "%.*s",
(int)(matches[1].rm_eo - matches[1].rm_so),
input + matches[1].rm_so);
printf("捕獲組1: [%s]\n", buf);
} else {
fprintf(stderr, "匹配錯誤: %d\n", ret);
}
// 4. 釋放資源
regfree(®ex);
return 0;
}
/* 輸出:
整體匹配: [Abc1234]
捕獲組1: [1234]
*/
關鍵注意事項
- 線程安全:
regex_t 編譯後為只讀,可多線程共享 regexec;但 regcomp/regfree 非線程安全。
- 性能:POSIX 正則引擎為 NFA 回溯實現,複雜模式(如嵌套量詞)易發生災難性回溯。高性能場景建議使用 **PCRE2** 或 **RE2** 庫。
- 錯誤處理:
regcomp 失敗需調用 regerror 獲取可讀信息。
- 內存管理:
regmatch_t 數組由調用者分配,大小至少為捕獲組數 + 1。
- 字符編碼:POSIX 正則按字節處理,UTF-8 多字節字符可能被拆分匹配,需謹慎使用
. 和字符類。
POSIX ERE vs Perl/PCRE 語法差異速查
| 特性 | POSIX ERE | Perl/PCRE |
| 捕獲組 | (...) | (...) |
| 非捕獲組 | 不支持 | (?:...) |
| 前瞻/後顧 | 不支持 | (?=...) (?!...) |
| 貪婪/懶惰量詞 | 僅貪婪 * + ? {m,n} | *? +? ?? {m,n}? |
| 反向引用 | \1-\code{\9} | \1-\code{\9、\g{10} |
| 字符類簡寫 | [:digit:] 等 POSIX 類 | \d \w \s 等 |
| 單詞邊界 | 不支持 | \b \B |
替代方案推薦
- PCRE2:Perl 兼容、功能最全、廣泛使用(PHP、R、Apache、Nginx)。
- RE2:Google 開發、保證線性時間、無回溯風險、適合高併發服務。
- C++11
<regex>:標準庫封裝,默認 ECMAScript 語法,也支持 std::regex_constants::extended (POSIX ERE)。