C ++ стандартное регулярное выражение разница между std = c ++ 11 и std = gnu ++ 11 - PullRequest
1 голос
/ 15 октября 2019

Кажется, что есть разница в поведении регулярных выражений при компиляции кода с использованием расширений регулярных выражений и gnu.

Следующий код вызывает исключение при компиляции с -std = c ++ 11, однако -std = gnu ++11 работает:

#include <regex>
#include <iostream>

int main(int argc, char **argv) {

    std::string rex { "\\[1\\]" };
    std::string str { "[1]" };
    std::regex regex(rex, std::regex::extended);
    auto match = std::regex_match(str.begin(), str.end(), regex);
    std::cout << "Result is " << match << std::endl;
    return 0;
}

Я пробовал gcc с 4.9.4 до 9.2 с тем же поведением. Есть идеи, почему этот код ведет себя по-другому?

1 Ответ

3 голосов
/ 15 октября 2019

std::regex::extended использует расширенные регулярные выражения POSIX . Согласно этим правилам синтаксиса, обратная косая черта может предшествовать только «специальному символу», который является одним из .[\()*+?{|^$. Левая скобка [ является специальным символом, а правая скобка ] - нет. Таким образом, ваше регулярное выражение должно быть "\\[1]" вместо "\\[1\\]" для соответствия стандарту.

Глядя на исходный код стандартной библиотеки, в regex_scanner.tcc есть следующее:

#ifdef __STRICT_ANSI__
      // POSIX says it is undefined to escape ordinary characters
      __throw_regex_error(regex_constants::error_escape,
                  "Unexpected escape character.");
#else
      _M_token = _S_token_ord_char;
      _M_value.assign(1, __c);
#endif

Что показывает, что это расширение GNU, позволяющее экранировать не специальные символы. Я не знаю, где это расширение задокументировано.

...