透過括號 () 分解正則表達式為子表達式,使用下標 [] 存取:0 為整體,1 為第一組括號,依序遞增。結合 matched 檢查選擇性群組是否匹配,實現複雜格式驗證。
#include <iostream>
#include <string>
#include <boost/regex.hpp>
using namespace std;
using namespace boost;
// 驗證邏輯:分析子表達式匹配狀態
bool valid(const boost::smatch& m) {
// 模式:(\()?(\d{3})(\))?([-. ])?(\d{3})([-. ]?)(\d{4})
// 群組:1=左括號 2=區號 3=右括號 4=分隔符1 5=前3碼 6=分隔符2 7=後4碼
if (m[1].matched) { // 有左括號
// 必須有右括號,且分隔符1 為空或空格
return m[3].matched && (m[4].matched == 0 || m[4].str() == " ");
} else { // 無左括號
// 不可有右括號,且分隔符1 必須等於分隔符2
return !m[3].matched && m[4].str() == m[6].str();
}
}
int main() {
// 電話號碼模式:支援 (xxx)xxx-xxxx, xxx-xxx-xxxx, xxx.xxx.xxxx 等
std::string phone = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ]?)(\\d{4})";
boost::regex r(phone);
boost::smatch m;
std::string s("(432)312-3425 9424151424 15");
// 遍歷所有匹配並驗證
for (boost::sregex_iterator it(s.begin(), s.end(), r), end_it;
it != end_it; ++it) {
if (valid(*it)) {
std::cout << "valid : " << it->str() << std::endl;
} else {
std::cout << "not valid : " << it->str() << std::endl;
}
}
}
valid : (432)312-3425 valid : 9424151424
| 群組 | 模式 | 說明 |
|---|---|---|
| 1 | (\\()? | 可選左括號 |
| 2 | (\\d{3}) | 區號 3 位數 |
| 3 | (\\))? | 可選右括號 |
| 4 | ([-. ])? | 可選分隔符:- . 空格 |
| 5 | (\\d{3}) | 前 3 碼 |
| 6 | ([-. ]?) | 可選分隔符 |
| 7 | (\\d{4}) | 後 4 碼 |
(xxx) xxx-xxxx 或 (xxx)xxx-xxxx → 必須成對括號,分隔符可為空或空格xxx-xxx-xxxx 或 xxx.xxx.xxxx → 兩分隔符必須一致(xxx-xxx-xxxx(括號不成對)、xxx-xxx xxxx(分隔符不一致)此技術廣泛應用於表單驗證、日誌解析、資料清洗等場景。