16

Why can't I use lookbehinds in C++11? Lookahead works fine.

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

This will throw the following exception:

The expression contained mismatched ( and ).

This wont throw any exception:

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

What am I missing?

ildjarn
  • 62,044
  • 9
  • 127
  • 211
Carlj901
  • 1,329
  • 4
  • 24
  • 39

2 Answers2

21

C++11 <regex> uses ECMAScript's (ECMA-262) regex syntax, so it will not have look-behind (other flavors of regex that C++11 supports also don't have look-behind).

If your use case requires the use of look-behind, you may consider using Boost.Regex instead.

ThomasMcLeod
  • 7,603
  • 4
  • 42
  • 80
nhahtdh
  • 55,989
  • 15
  • 126
  • 162
2

A positive lookbehind (?<=a) matches a location in a string that is immediately preceded with the lookbehind pattern. In case overlapping matches are not expected, like the case here, you can simply use a capturing group and extract just the Group 1 (or even more group values if you specify more than one):

a(b)

Here is a way to extract all matches using 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;
}

If you only need to extract the first match use regex_search (not regex_match as this function requires a full string match):

std::smatch sm;
if (regex_search(sentence, sm, rx)) {
    std::cout << sm[1] << std::endl;
}

See the C++ demo.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563