Unterschied zwischen regex_match und regex_search?

Lesezeit: 4 Minuten

Benutzer-Avatar
Irgendein Programmierer

Ich habe mit regulären Ausdrücken experimentiert, um eine Antwort auf diese Frage zu geben, und festgestellt, dass während regex_match findet eine Übereinstimmung, regex_search nicht.

Das folgende Programm wurde mit g++ 4.7.1 kompiliert:

#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";
}

Ausgabe:

regex_match: match
regex_search: no match

Ist meine Annahme, dass beide übereinstimmen sollten, falsch, oder könnte es ein Problem mit der Bibliothek in GCC 4.7.1 geben?

  • Die Regex-Bibliothek von GCC ist noch weitgehend unimplementiert (GCC YU SHIP BROKEN <regex>?), also neige ich dazu zu sagen, ja, es ist ein Problem mit der Bibliothek.

    – R.Martinho Fernandes

    24. Juli 2012 um 9:37 Uhr


  • Ihr Programm liefert zweimal eine Übereinstimmung mit VS2010, daher liegt das Problem vermutlich in der Bibliothek, die gcc verwendet. Haben Sie versucht, die Boost-Version der Regex-Bibliothek zu verwenden?

    – Verrückter Wissenschaftler

    24. Juli 2012 um 10:00 Uhr

  • @H2CO3 Sie können auch Assembly verwenden, aber das möchten Sie vielleicht nicht 🙂 Dasselbe gilt für C-Funktionen, die in C++ enthalten sind. Sie brechen den C++-Programmierstil (z. B. müssen Sie anfangen, nach Rückgabecodes zu suchen, anstatt sich um Ausnahmen zu kümmern).

    – Betabandido

    24. Juli 2012 um 11:39 Uhr


  • @H2CO3 Ja natürlich, aber im Moment versuche ich den neuen C++11 Standard mit all seinen Features kennenzulernen. In einem realen Szenario würde ich wahrscheinlich Boost oder was auch immer im System verfügbar ist (wie die Standard-POSIX-Funktionalität) verwenden.

    – Irgendein Programmierer-Typ

    24. Juli 2012 um 11:40 Uhr

  • @H2CO3 🙂 Ich würde definitiv POSIX-Regex (oder Boost.Regex) verwenden, wenn ich so etwas in echtem Code implementieren müsste. Aber die Frage des OP ist gut. Eigentlich frage ich mich, warum GCC beschlossen hat, eine kaputte Implementierung regulärer Ausdrücke zu veröffentlichen. Lieber gar keine Stütze als eine kaputte…

    – Betabandido

    24. Juli 2012 um 12:01 Uhr

Angenommen, C++ und Regex steigern haben eine ähnliche Struktur und Funktionalität, der Unterschied zwischen regex_match und regex_search wird erklärt hier:

Das regex_match() Der Algorithmus meldet nur Erfolg, wenn die Regex mit der gesamten Eingabe von Anfang bis Ende übereinstimmt. Wenn die Regex nur mit einem Teil der Eingabe übereinstimmt, regex_match() wird falsch zurückgegeben. Wenn Sie die Zeichenfolge nach Teilzeichenfolgen durchsuchen möchten, die mit der Regex übereinstimmen, verwenden Sie die regex_search() Algorithmus.

Benutzer-Avatar
Gummistiefel

Ihre Regex funktioniert gut (beide stimmen überein, was richtig ist) in VS 2012rc.

Unter g++ 4.7.1 (-std=gnu++11)bei Verwendung von:

  • ".*FILE_(.+)_EVENT\\.DAT.*", regex_match passt, aber regex_search nicht.
  • ".*?FILE_(.+?)_EVENT\\.DAT.*"weder regex_match Noch regex_search Streichhölzer (O_o).

Alle Varianten sollten übereinstimmen, einige jedoch nicht (aus Gründen, auf die bereits von betabandido hingewiesen wurde). Unter g++ 4.6.3 (-std=gnu++0x)ist das Verhalten identisch mit g++ 4.7.1.

Steigerung (1,50) passt alles richtig zusammen mit beiden Mustervarianten.

Zusammenfassung:

                        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
 -----------------------------------------------------

In Bezug auf Ihr Muster, wenn Sie gemein ein Punktzeichen '.'dann solltest du so schreiben ("\\."). Sie können das Backtracking auch reduzieren, indem Sie nicht gierige Modifikatoren verwenden (?):

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

Durchsuchen der neuesten libstdc++ Quellcode zum regex_searchdu wirst finden:

* @todo Implement this function.

Leider ist dies nicht der einzige verbleibende TODO-Eintrag. GCCs <regex> Die Umsetzung ist derzeit noch unvollständig. Ich empfehle die Verwendung von Boost oder Clang und #ifdef den Code, bis GCC aufgeholt hat.

(Dies wurde auch im 4.8-Zweig nicht behoben.)

Benutzer-Avatar
Betabandido

Ich habe versucht, die Regex-Bibliothek in C++11 zu verwenden, und bin auf viele Probleme gestoßen (beide mit g++ 4.6 und 4.7). Grundsätzlich ist die Unterstützung entweder nicht da oder es gibt nur eine teilweise Unterstützung. Das gilt sogar für die SVN-Version. Hier haben Sie einen Link, der die beschreibt aktueller Status für die SVN-Version von libstdc++.

Daher denke ich, dass es vorerst die beste Option ist, die Verwendung fortzusetzen Boost.Regex.

Alternativ können Sie versuchen, zu verwenden libc++. Entsprechend dieses Dokumentdie Unterstützung für reguläre Ausdrücke ist abgeschlossen.

1012890cookie-checkUnterschied zwischen regex_match und regex_search?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy