在C++11中使用正则表达式的后顾断言

17

为什么我不能在C++11中使用lookbehinds?Lookahead可以正常工作。

std::regex e("(?<=a)b");

这将抛出以下异常:

The expression contained mismatched ( and ).

这段代码不会抛出任何异常:

std::regex e("a(?=b)");

我错过了什么?


4
如果您正在使用gcc,请注意,大多数正则表达式的功能尚未实现。 - Stephan Dollberg
@Carlj901 你是如何设置你的工作环境的?你下载和安装了哪些软件? - ComFreek
有趣。我找到的std::regex_search的文档并没有提到它会抛出异常。我本以为使用扩展的正则表达式限定符会起作用,但事实并非如此。好问题。 - undefined
2个回答

22

C++11中的<regex>使用ECMAScript(ECMA-262)的正则表达式语法,因此它不支持回顾后发(C++11支持的其他正则表达式风格也不支持回顾后发)。

如果您的用例需要使用回顾后发,则可以考虑改用Boost.Regex


你知道Boost正则表达式是否支持它吗? - Carlj901
@Carlj901:快速谷歌搜索显示,boost支持Perl语法下的后顾断言。 - nhahtdh
令人惊讶的是,https://regex101.com/ 上的 ECMAScript 模式支持回顾后发表达式。 - The Dreams Wind
没问题,ES2018已经添加了后行断言。https://github.com/tc39/proposal-regexp-lookbehind - maattdd

2
一个正向 后顾断言 (?<=a) 匹配字符串中紧接在后顾断言模式之前的位置。如果不希望出现重叠匹配,就像这里的情况一样,您可以简单地使用一个捕获组并仅提取第一组(甚至更多的组值,如果您指定了多个)。
a(b)

这里有一种使用 std::sregex_token_iterator 提取所有匹配项的方法:
#include <iostream>
#include <vector>
#include <regex>

int main() {
    std::regex rx("a(b)");             // A pattern with a capturing group
    std::string sentence("abba abec"); // A test string
    std::vector<std::string> names(std::sregex_token_iterator(
        sentence.begin(), sentence.end(), rx, 1), // "1" makes it return Group 1 values
        std::sregex_token_iterator()
    );
    for( auto & p : names ) std::cout << p << std::endl; // Print matches
    return 0;
}

如果你只需要提取第一个匹配项,使用regex_search(不要使用regex_match,因为这个函数需要完全的字符串匹配):
std::smatch sm;
if (regex_search(sentence, sm, rx)) {
    std::cout << sm[1] << std::endl;
}

查看C++演示

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接