Разница между 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?
Ответы
Ответ 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С++. Согласно этот документ, поддержка регулярных выражений завершена.