Weiter zu meiner vorherigen Frage: ECMAScript Regex für eine mehrzeilige Zeichenfolge , Ich habe das folgende Ladeverfahren implementiert:
%Vor%Das Laden mit dieser Datei führt jedoch zu einem Stapelüberlauf (Parameter: 0x00000001, 0x00332FE4):
%Vor% Ich konnte die Quelle des Stack-Überlaufs nicht finden, aber es sieht so aus, als wäre die äußere std::sregex_iterator
-Schleife verantwortlich.
Vielen Dank im Voraus!
Hier ist ein weiterer Versuch:
%Vor%In Ihrem C ++ wäre es natürlich geschrieben als:
%Vor%Es ist für ein minimales Backtracking gemacht (zumindest wenn es zusammenpasst), obwohl ich im Moment ein bisschen Mr. Tired-Face bin, also wahrscheinlich einige Wege verpasst habe, es zu verbessern.
Es macht zwei Annahmen , die verwendet werden, um eine Menge Backtracking zu vermeiden (was möglicherweise den Stapelüberlauf verursacht, wie andere gesagt haben):
===
gibt, außer für die Start- / End-Markierungslinien. ?!
). Es sollte, in Anbetracht seiner ECMAScript Dialekt. Erklärt:
%Vor% Passen Sie die Objektstartmarkierung an und erfassen Sie sie. Das [^=]
ist eine Möglichkeit, eine relativ kleine Menge an Backtracking zu vermeiden, genau wie bei Ihnen - wir verwenden nicht [^ ]
, weil ich nicht weiß, ob es Leerzeichen in der OBJECT-ID gibt.
Beginnen Sie, eine Gruppe für Daten zu erfassen. Darin befindet sich eine nicht-einfangende Gruppe, da wir jede Zeile einzeln anpassen.
%Vor% Negative Lookahead - wir wollen nicht ===
am Anfang unserer erfassten Zeile.
Entspricht einer Zeile einzeln.
%Vor%Passen Sie mindestens eine Zeile zwischen Anfangs- und Endmarkierungen an, und erfassen Sie dann ALLE Zeilen in einer einzelnen Gruppe.
%Vor%Passen Sie die Endmarke an.
Vergleich (mit RegexBuddy):
Originalversion:
Jedes hinzugefügte Objekt bewirkt, dass die Anzahl der Schritte für die vorherigen vergrößert wird. Wenn beispielsweise ein weiteres Objekt (Kopie von Objekt 2, umbenannt in 3) hinzugefügt wird, ergeben sich: 2203 Schritte, 1322 Schritte, 425 Schritte.
Diese Version:
Heiliges katastrophales Zurückverfolgen. Der Schuldige ist (?:.|\n)*
. Wann immer Sie ein Konstrukt wie dieses sehen, wissen Sie, dass Sie nach Ärger fragen.
Warum? Weil Sie der Engine sagen, dass sie so oft wie möglich oder gar keinem anderen Zeichen (außer Newline) oder Newline entsprechen soll. Lass mich dich durchgehen.
Die Engine wird wie erwartet gestartet und entspricht dem === OBJECT2 ===
-Teil ohne größere Probleme, ein Newline wird verbraucht und die Hölle beginnt dann. Die Engine verbraucht ALLES bis hinunter zu === END OBJECT1 ===
und geht von dort zu einem passenden Match zurück. Backtracking bedeutet grundsätzlich, einen Schritt zurückzugehen und die Regex erneut anzuwenden, um zu sehen, ob es funktioniert. Grundsätzlich versuchen Sie alle möglichen Permutationen mit Ihrer Zeichenfolge. Dies wird in Ihrem Fall zu einigen hunderttausend Versuchen führen. Das ist wahrscheinlich der Grund, warum Sachen für dich problematisch sind.
Ich weiß nicht, ob Ihr Code besser ist oder ob er irgendwelche Fehler enthält, aber (?:.|\n)*
entspricht dem Schreiben von .*
mit dem * s * einzelnen Zeilenmodifikator (dot stimmt mit Zeilenumbrüchen überein) oder [\S\s]*
. Wenn Sie dieses Konstrukt durch eines der beiden ersetzen, die ich empfohlen habe, werden Sie hoffentlich keinen Stapelüberlauffehler mehr sehen.
Bearbeiten: Schauen Sie sich auch die anderen Lösungen an, ich hatte nicht wirklich Zeit, in die Tiefe zu gehen und Ihnen eine solide Lösung für Ihr Problem zu bieten, zusätzlich zu erklären, warum es so schlimm ist.
Ihre Ausdrücke scheinen eine Menge Backtracking zu verursachen. Ich würde deine Ausdrücke ändern zu:
Erstens: ^===\s+(.*?)\s+===[\r\n]+^(.*?)[\r\n]+^===\s+END\s+\s+===
Zweitens: ^<([^>]+)>:([^<]*)
Beide Ausdrücke funktionieren mit den Optionen: Multiline und DotMatchesAll. Mit dem Start des Zeilenankers ^
wird das Backtracking auf maximal eine Zeile oder eine Gruppe begrenzt.
Tags und Links c++ regex c++11 stack-overflow standard-library