正規表達式零寬斷言
适用場景:比對/提取/查找/替換以 xxx 開頭,或以 xxx 結尾,但不包括 xxx 的字元串。
零寬斷言 | 用法 | 含義 |
---|---|---|
零寬度正預測先行斷言 lookahead | | 之後必須比對 ,但比對結果不含 |
零寬度負預測先行斷言 lookahead | | 之後必須不比對 |
零寬度正回顧後發斷言 lookbehind | | 之前必須比對 |
零寬度負回顧後發斷言 lookbehind | | 之前必須不比對 |
示例:提取
【123】
中的
123
的正規表達式:
(?<=【)\d+(?=】)
問題描述
正規表達式比對形似
qq=123456
的字元串,從中提取
123456
,但不包括
qq=
。首先想到的是直接利用零寬斷言 lookbehind 去比對,正規表達式很容易寫出來
(?<=qq=)[0-9]+
,但是在 C++ 運作階段報錯:
terminate called after throwing an instance of 'std::regex_error'
what(): Invalid special open parenthesis.
Aborted (core dumped)
問題分析
目前 C++ 标準庫正規表達式不支援零寬後行斷言(也叫零寬度正回顧後發斷言,lookbehind),即
(?<=exp)
和
(?<!exp)
文法。但支援零寬前行斷言(lookahead)。
Finally, flavors like std::regex and Tcl do not support lookbehind at all, even though they do support lookahead. JavaScript was like that for the longest time since its inception. But now lookbehind is part of the ECMAScript 2018 specification. As of this writing (late 2019), Google’s Chrome browser is the only popular JavaScript implementation that supports lookbehind. So if cross-browser compatibility matters, you can’t use lookbehind in JavaScript.
解決方案
- 構造 regex 時指定可選标志,使用其他正規表達式文法 ==> 驗證失敗 😦
- 把待提取部分用()括起來,作為一個獨立子表達式 ==> 驗證可行 😃
- 使用支援 lookbehind 的 Boost 正則 ==> 未驗證
示例代碼
#include <iostream>
#include <regex>
#include <string>
using namespace std;
using namespace regex_constants;
int main()
{
string seq = "[optional]qq=123456;";
string pattern_nok = "(?<=qq=)[0-9]+"; // C++ 正規表達式不支援 lookbehind,運作時報錯
string pattern = "qq=([0-9]+)"; // 将數字部分單獨作為一個子表達式
regex r(pattern /*, extended*/); // 可以在這裡修改預設正規表達式文法,然而并沒有什麼用
smatch results;
if (regex_search(seq, results, r))
{
cout << results[0] << endl; // 列印整個比對
cout << results[1] << endl; // 列印第一個正則子表達式
}
}
輸出結果
qq=123456
123456
Reference
https://c.runoob.com/front-end/854/
http://c.biancheng.net/cpp/html/1414.html
https://www.zhihu.com/question/391339488
https://bbs.csdn.net/topics/397367228?list=78619228
https://blog.csdn.net/qq_34651940/article/details/78885096
https://www.cnblogs.com/ProjectDD/p/10634300.html
https://www.jianshu.com/p/b5194398efb2
https://cuiqingcai.com/5788.html