天天看點

C++ 正規表達式 零寬斷言 lookbehind

正規表達式零寬斷言

适用場景:比對/提取/查找/替換以 xxx 開頭,或以 xxx 結尾,但不包括 xxx 的字元串。

零寬斷言 用法 含義

(?=exp)

零寬度正預測先行斷言 lookahead

exp1(?=exp2)

exp1

之後必須比對

exp2

,但比對結果不含

exp2

(?!exp)

零寬度負預測先行斷言 lookahead

exp1(?!exp2)

exp1

之後必須不比對

exp2

(?<=exp)

零寬度正回顧後發斷言 lookbehind

(?<=exp0)exp1

exp1

之前必須比對

exp0

exp0

(?<!exp)

零寬度負回顧後發斷言 lookbehind

(?<!exp0)exp1

exp1

之前必須不比對

exp0

示例:提取

【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.

解決方案

  1. 構造 regex 時指定可選标志,使用其他正規表達式文法 ==> 驗證失敗 😦
  2. 把待提取部分用()括起來,作為一個獨立子表達式 ==> 驗證可行 😃
  3. 使用支援 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

繼續閱讀