Lookahead-Operator für reguläre Ausdrücke (zwei oder mehr Wörter in String unabhängig von der Reihenfolge finden)



  • Angenommen, ich habe folgenden String

    string bsp {"Hier drin soll mit dem Ausdruck gesucht werden"};
    

    Es soll nun z. B. nach den beiden Wörtern 'soll' und 'Ausdruck' gesucht, weil es für den weiteren Verlauf wichtig ist, dass beide gleichzeitig gefunden werden, also vorkommen. Beide Wörter sind in jeweils einem eigenen String abgelegt (eingelesen worden), also

    string Wort_1 {"soll"};
    string Wort_2{"Ausdruck"};
    

    Wie kann ich nach beiden Wörtern mit einem Ausdruck suchen, der nur dann etwas findet, wenn beide Wörter gefunden werden, nicht nur eins. Ein logisches Und für reguläre Ausdrücke wäre schön, so wie es ja auch das Oder | gibt. Nachdem ich mich umgesehen habe, habe ich folgenden Ansatz (in diversen Variationen) versucht:

    regex rep (?=.*Wort_1)(?=.*Wort_2);
    

    Funktioniert hat es kein einziges Mal, aber wenn ich die Erklärungen zu diesem ?= Operator richtig verstanden habe, dann ist das genau das, was ich brauche, allerdings bekomme ich es auch nach vielen Versuchen nicht richtig hin. Kann mir jemand helfen oder gibt es gar einen anderen Weg?



  • Dieser Thread wurde von Moderator/in Arcoth aus dem Forum C++ (alle ISO-Standards) in das Forum Rund um die Programmierung verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Nutzt du vielleicht einen alten Compiler bzw eine alte libstdc++, z.B. g++ 4.8?

    Dieses Programm gibt mit neueren g++ 1 zurück:

    #include <regex>
    int main() {
      std::regex r("^(?=.*soll)(?=.*Ausdruck)");
      return std::regex_match("Hier drin soll mit dem Ausdruck gesucht werden", r);
    }
    

    Probiere ansonsten bei älteren Compilern boost::regex.



  • Am Compiler sollte es nicht liegen, ich habe auf Windows den MinGW 4.9.2. Dein Miniprogramm läuft auch bei mir. Ich verstehe nur nicht, warum das ^ vor dem Ausdruck stehen muss.

    Und wenn ich die beiden Wörter nicht dirket reinschreibe, wie im Miniprogramm, sondern in mehreren Schleifendurchgängen immer wieder nach zwei anderen suchen will, wie bringe ich dann die beiden Variablennamen in dem Ausdruck richtig unter?



  • Alex1994 schrieb:

    Am Compiler sollte es nicht liegen, ich habe auf Windows den MinGW 4.9.2. Dein Miniprogramm läuft auch bei mir. Ich verstehe nur nicht, warum das ^ vor dem Ausdruck stehen muss.

    Muss nicht, kann aber. Es schadet nie, eine Regex zu verankern, wenn das möglich ist. Gibt meistens bessere Performance. Denn wenn nach dem nullten Buchstaben nicht beide Wörter irgendwo dahinter folgen, braucht man nicht zu testen, ob nach dem ersten Buchstaben beide Wörter irgendwo dahinter folgen - das geht schlicht nicht, d.h. man kann das Backtracking abbrechen. Daher kann&sollte man verankern.

    Du solltest dir eher über andere Dinge Gedanken machen. Was ist zum Beispiel, wenn du die beiden Wörter "Fluss" und "Flussbett" suchst. Dann findest du nämlich aktuell beides, auch wenn nur "Flussbett" vorkommt, da "Fluss" in "Flussbett" gefunden wird. Also evtl. mit \b auf Wortgrenzen testen.

    Und wenn ich die beiden Wörter nicht dirket reinschreibe, wie im Miniprogramm, sondern in mehreren Schleifendurchgängen immer wieder nach zwei anderen suchen will, wie bringe ich dann die beiden Variablennamen in dem Ausdruck richtig unter?

    Einfach den String zusammenbauen?! Wo ist das Problem?
    Allerdings beachte, dass die Suchwörter hoffentlich nur aus dem Programm kommen und nicht von extern. Es ist fast nie eine gute Idee, eine Regex so bei zusammenzusetzen. Nen einfaches find könnte es doch auch tun oder brauchst du das wirklich als RE?



  • Ein Ansatz für dasselbe Problem, nur diesmal mit zwei Stringvariablen, in denen die jeweiligen Wörter stehen, nach denen gerade gesucht wird:

    string Wort1 {"Beispiel1};
    string Wort2 {"Beispiel2};
    
    regex r("^(?=.*\b Wort1 \b)(?=.*\b Wort2 \b)");
    

    So werden aber Wort1 und Wort2 nicht als Variablen erkannt, also habe ich versucht, den Audruck so umzuformen, dass sie als solche erkannt werden, aber das führte zu Resultaten, die nicht funktioniert haben. Der Ausdruck oben liefert keine Fehlermeldung zurück, aber tut nicht das, was ich eigenltich intendiere. Wie muss das denn aussehen, dass es das tut, was ich vorhabe?

    Entschuldigt bitte, wenn das ganze etwas unbeholfen wirken sollte, aber irgendwie tu ich mir mit (komplizierteren) regulären Ausdrücken schwerer als mit anderen Programmierthemen. Ich betreibe das ganze auch nicht im Rahmen eines Studiums oder sowas, sondern alles auf freiwilliger Basis und allein und auch noch nicht allzu lange.



  • Du suchst hier nach Wortgrenze-Space-Wort1-Space-Wortgrenze. Du willst aber weder nach Space noch nach Wort1 suchen, sondern nach Wortgrenze-Beispiel1-Wortgrenze.

    Warum sollten plötzlich in einem String Variablen interpoliert werden?! Du musst schon den Inhalt der Variablen Wort1 einsetzen, nicht "Wort1".

    String-Verkettung geht unter anderem mit dem operator+.



  • Und \b geht natürlich nur in einem R-gequoteten String, sonst musst du \\b schreiben.

    Also:
    "\\b"
    oder insbesondere für REs besser:
    R"(\b)"



  • Das soll nicht auf einmal interpoliert werden, das war mein ursprüngliches Vorhaben, dass das mit Variablennamen geht, sodass dann automatisch immer die Inhalte dieser Variablen in den regulären Ausdruck gesetzt werden und dann nach diesen beiden Inhalten gesucht wird.

    Das mit dem +-Operator weiß ich, damit habe ich versucht den Ausdruck oben zu modifizieren. Mit anderen regulären Ausdrücken habe ich das auch hinbekommen, aber hier mache ich irgendwas falsch.

    Edit: Ja, stimmt, das habe ich falsch gemacht. Normalerweise benutze ich R-gequotete REs.


Anmelden zum Antworten