C++: Reguläre Audrücke verstehen und umsetzen



  • Es gibt nicht "die" Regex-Syntax, es gibt verschiedene Dialekte. Was egrep verwendet weiss ich nicht. Kannst du aber sicher irgendwo nachlesen. Die Dialekte sind sich aber sehr ähnlich, und gerade einfache Dinge sind quasi überall gleich. Also allgemein... ja, sollte im grossen und ganzen schon hinhauen.

    Davon abgesehen: egrep ist ein Command-Line Tool. Und so ein Command-Line Tool bekommt nicht in jedem Fall 1:1 das gefüttert was du in der Shell eintippst. Da spielt noch das Escaping der Shell mit rein.

    Also angenommen du willst mit ner Regex nach einem Stern suchen. Dann muss du den für die Regex erstmal escapen, also \*. Wenn deine Shell jetzt ebenso \ als Escape-Character verwendet, dann musst du das nochmal escapen: \\*. Und damit die Shell weiss dass sie nicht globben soll, solltest du das ganze noch quoten: "\\*"

    D.h. "\\*" als Argument für egrep entspricht der Regex \*.



  • @hustbaer, danke für die Erläuterung! Kriegst dafür ein Salbei-Bonbon 😛 🙂

    Habe auch schon das Buch "Reguläre Ausdrücke" bekommen. Echt super erklärt!



  • @wob, das mit dem Doppelbackslash funktioniert bei mir nicht. Es wird dann der gesamte String ausgegeben.

    Und wie bekomme ich es hin, mehrere Funde auszugeben? Wenn in dem String z.B. zwei mal der selbe Text vorkommt, nur mit zwei unterschiedlichen Alter? Ich habe es bereits mit

    cm[1].str()  //erster Fund
    cm[2].str()  //zweiter Fund
    

    versucht, aber die Anweisung cm[2].str() gibt nur einen leeren String zurück.



  • @DerDaVinciKot Zeig mal ein minimales aber vollständiges Beispiel wo das Problem auftritt. Es wurde in diesem Thread einiges geschrieben/empfholen und zumindest ich bin mir jetzt nicht sicher was du davon wie umgesetzt hast/wie dein Code jetzt aussieht.



  • Das tu ich doch gern!

    std::regex re(R"(Peter ist (\d+) Jahre alt.*)");
        std::cmatch cm;
        std::regex_match("Peter ist 70 Jahre alt und hat bereits Probleme sich die Schuhe anzuziehen.Peter ist 80 Jahre alt und hat bereits Probleme sich die Schuhe anzuziehen.", cm, re);
    
        qDebug() << QString::fromStdString(cm[1].str());               
        qDebug() << QString::fromStdString(cm[2].str());
    

    Ausgabe:
    "70"
    ""
    Wie bekomme ich es hin, beide Altersangaben (70 und 80) auszugeben?



  • #include <string>
    #include <regex>
    
    int main()
    {
        std::regex re(R"(Peter ist (\d+) Jahre alt)");
        std::smatch sm;
        std::string searchText = "Peter ist 70 Jahre alt und hat bereits Probleme sich die Schuhe anzuziehen.Peter ist 80 Jahre alt und hat bereits Probleme sich die Schuhe anzuziehen.";
    
        while(std::regex_search(searchText, sm, re))
        {
            std::cout << "entire match: " << sm.str() << "\n";
            for (std::size_t i = 1; i < sm.size(); ++i)
                std::cout << "capture group " << i << ": " << sm[i].str() << "\n";
            searchText = sm.suffix();
        }
    }
    

    Pass das für deine Qt bedürfnisse an.
    Das geht sich besser, weil searchText = sm.suffix(); ist jetzt nicht das performanteste auf der Welt, aber ich hab das schnell zusammenschmissen.



  • Du kannst auch einen regex_iterator nutzen:

    std::regex re(R"(Peter ist (\d+) Jahre alt)");
    std::string s("Peter ist 70 Jahre alt. Oder: Peter ist 60 Jahre alt?");
    auto resultIt = std::sregex_iterator(s.begin(), s.end(), re);
    for (auto it = resultIt; it != std::sregex_iterator(); ++it) {
        std::cout << "Ganzer Match: |" << it->str() << "|, das Alter ist: |" << (*it)[1].str() << "|\n";
    }
    


  • Da @DerDaVinciKot Qt in seinem Projekt verwendet schmeiß ich mal in dem Raum, dass Qt auch selbst eine Regex klasse hat. https://doc.qt.io/qt-5/qregularexpression.html



  • Hey, Ihr seid echt spitze! Beide Codes funktionieren. Ich werde mich da mal durcharbeiten damit ich das ganze auch wirklich verstehe.

    Ein schönes Wochenende noch



  • Wie mache ich es, bei regex Groß- und Kleinschreibung zu ignorieren? Beispiel:

    std::string s = "Mein Name ist Peter Pan.";
    std::regex rex("Peter");
    if (std::regex_search(s, rex))
    {
        qDebug() << "Gefunden!";
    }
    

    Ich möchte das "Peter", "peter", "PETER" usw gefunden wird. Das lässt sich zwar mit Zeichenklassen lösen: [Pp][Ee][Tt]Ee]Rr], aber es soll auch eine viel einfachere Funktion geben die Groß- und Kleinschreibung ignoriert. Bei egrep geht das z.B. mit -i. Wie bekomme ich das in C++ hin?



  • std::regex r{"bla", std::regex_constants::icase}
    

    https://en.cppreference.com/w/cpp/regex/syntax_option_type



  • Danke, das klappt super! Allerdings wirkt es auf den kompletten regulären Ausdruck. Gibt es eine Möglichkeit, das dass Ingorieren von Groß- und Kleinschreibung sich nur auf einen Teil bezieht? Also in diesem Fall nur auf den Namen?



  • Ich glaube nicht dass das funktioniert aber probiere mal: (?i)bla. Wenn das wie erwartet mit den verschiedenen unterstützten Varianten in C++ nicht funktioniert (ECMAScript, basic, extended, awk, grep, egrep). (Änderbar wie die icase option).

    Dann fiele mir noch ein den Qt Regex zu versuchen, wie von firefly vorgeschlagen, vielleicht unterstütz der diesen marker.



  • Dieser Beitrag wurde gelöscht!


  • Das schluckt der Compiler leider nicht:
    terminate called after throwing an instance of 'std::regex_error'
    what(): Invalid special open parenthesis.


Anmelden zum Antworten