Подтвердить что ты не робот

Разница между regex_match и regex_search?

Я экспериментировал с регулярным выражением, пытаясь ответить на этот вопрос, и обнаружил, что, пока regex_match находит совпадение, regex_search нет.

Следующая программа была скомпилирована с g++ 4.7.1:

#include <regex>
#include <iostream>

int main()
{
    const std::string s = "/home/toto/FILE_mysymbol_EVENT.DAT";
    std::regex rgx(".*FILE_(.+)_EVENT\\.DAT.*");
    std::smatch match;

    if (std::regex_match(s.begin(), s.end(), rgx))
        std::cout << "regex_match: match\n";
    else
        std::cout << "regex_match: no match\n";

    if (std::regex_search(s.begin(), s.end(), match, rgx))
        std::cout << "regex_search: match\n";
    else
        std::cout << "regex_search: no match\n";
}

Вывод:

regex_match: match
regex_search: no match

Является ли мое предположение, что оба должны совпадать с ошибкой, или может возникнуть проблема с библиотекой в ​​GCC 4.7.1?

4b9b3361

Ответ 1

Ваше регулярное выражение отлично работает (оба соответствуют, что правильно) в VS 2012rc.

В g++ 4.7.1 (-std=gnu++11), если использовать:

  • ".*FILE_(.+)_EVENT\\.DAT.*", regex_match соответствует, но regex_search не работает.
  • ".*?FILE_(.+?)_EVENT\\.DAT.*", ни regex_match, ни regex_search не соответствует (O_o).

Все варианты должны совпадать, а некоторые нет (по причинам, которые уже были отмечены betabandido). В g++ 4.6.3 (-std=gnu++0x) поведение идентично g++ 4.7.1.

Boost (1.50) соответствует всем правильно w/обе разновидности шаблонов.

Резюме

                        regex_match      regex_search
 -----------------------------------------------------
 g++ 4.6.3 linux            OK/-               -
 g++ 4.7.1 linux            OK/-               -
 vs 2010                     OK                OK
 vs 2012rc                   OK                OK
 boost 1.50 win              OK                OK
 boost 1.50 linux            OK                OK
 -----------------------------------------------------

Что касается вашего шаблона, если вы имеете в виду символ точки '.', тогда вы должны написать так ("\\."). Вы также можете уменьшить обратную трассировку с помощью неживых модификаторов (?):

".*?FILE_(.+?)_EVENT\\.DAT.*"

Ответ 2

Предполагая, что С++ и Boost Regex имеют сходную структуру и функциональность, объясняется разница между regex_match и regex_search здесь:

Алгоритм regex_match() будет сообщать только об успехе, если регулярное выражение соответствует всему вводу, от начала до конца. Если регулярное выражение совпадает только часть ввода, regex_match() вернет false. Если ты хочешь для поиска строки, ищущей подстроки, для регулярного выражения совпадений, используйте алгоритм regex_search().

Ответ 3

Просматривая последний libstdС++ исходный код для regex_search, вы найдете:

* @todo Implement this function.

К сожалению, это далеко не единственный элемент TODO. Реализация GCC <regex> в настоящее время неполна. Я рекомендую использовать Boost или Clang и #ifdef код до тех пор, пока GCC не поймает.

(Это не было зафиксировано в ветке 4.8.)

Ответ 4

Я попытался использовать библиотеку регулярных выражений в С++ 11, и я столкнулся с множеством проблем (как с использованием g++ 4.6, так и 4.7). В принципе, поддержка либо отсутствует, либо есть лишь частичная поддержка. Это справедливо даже для версии SVN. Здесь у вас есть ссылка, описывающая текущее состояние для версии SVN версии libstdС++.

Итак, на данный момент, я думаю, лучший вариант - продолжить использование Boost.Regex.

В качестве альтернативы вы можете попробовать использовать libС++. Согласно этот документ, поддержка регулярных выражений завершена.