Ich versuche herauszufinden, ob eine Zeichenfolge richtig Klammern geschlossen hat.
Um dies zu tun, verwende ich die folgenden drei Klammerpaare.
%Vor%Die Klammern können auch verschachtelt sein, solange sie richtig formatiert sind.
%Vor%Ich habe versucht, Regex zu verwenden, und nach ein bisschen herumfummeln, habe ich das.
%Vor%Allerdings gibt es ein paar Probleme damit.
Es passt nur zu Klammern, aber nicht mit Klammern
Ich verstehe nicht, warum es nicht mit den Klammern übereinstimmt.
In meinen Beispielen habe ich eindeutig einen Backslash vor den Klammern verwendet.
Eingabe
%Vor% Laut diesem Artikel unterstützt Ruby ab Version 2.0 rekursive Regexps. Dies bedeutet, dass Sie das Ruby-spezifische Token \g<0>
verwenden können, um rekursiv die gesamte regexp-Datei an jedem beliebigen Punkt Ihrer regulären Ausgabe abzugleichen. Dieser Ansatz kann Stack effektiv emulieren, um Ihre Aufgabe zu lösen.
Hier ist die resultierende regexp:
%Code%
Diese aktualisierte Version behandelt Fälle wie folgt: [^(){}\[\]]*(\((\g<0>)?\)|\{(\g<0>)?\}|\[(\g<0>)?\])?[^(){}\[\]]*
, wenn mehrere Klammergruppen auf derselben Ebene sind. Danke @Jonny 5 für den Hinweis auf diesen Fall:
Dieser Ausdruck erfordert die Überprüfung, ob die gesamte Eingabezeichenfolge übereinstimmt. Teilweise Übereinstimmung bedeutet, dass in Klammern ein Fehler in der Reihenfolge der Zeichenfolge auftritt.
Hier ist eine andere Version, die nicht überprüfen muss, ob die gesamte Eingabezeichenfolge übereinstimmt:
%Vor%Sie werden möglicherweise feststellen, dass es versucht, das entsprechende Klammerpaar zu finden, und dann rekursiv mit sich selbst übereinstimmt. Ich habe es hier ausprobiert und es scheint zu funktionieren. Ich bin kein Ruby-Ingenieur, also kann ich keinen Ruby-Test durchführen, hoffe aber, dass es nicht nötig ist.
Dies ist wahrscheinlich ein schlechter Anwendungsfall für eine Regex, ich würde einen einfachen Stapelparser verwenden.
%Vor%edit: Cary Swoveland - schreiben Sie tatsächlichen Code und haben Leute kritisieren: - ?.
updated: Hatte einen kleinen Fehler darin, dass ich überprüft habe, ob das schließende Zeichen mit dem ersten übereinstimmt. repariere es!
Ich nehme an, Ihre Zeichenfolge besteht nur aus den Zeichen in der Zeichenfolge "()[]{}"
. Beachten Sie, dass für eine Zeichenfolge str
die Übereinstimmungsanforderung erfüllt ist:
str
muss leer sein oder einen Teilstring enthalten "()"
, "[]"
oder "[]"
; und str
nicht leer ist, erfüllt str
mit "()"
, "[]"
und "[]"
entfernt die Matching-Anforderung. Wir können daher Teilstringpaare nacheinander entfernen, bis wir es nicht mehr tun können. Wenn das, was übrig ist, leer ist, erfüllt die ursprüngliche Zeichenfolge die Übereinstimmungsanforderung; Sonst nicht:
%Vor% Bearbeiten: nach Jonny 5's Vorschlag verschoben
Nach dem Lesen der Kommentare unten und inspiriert von Aiveans Lösung, hier ist ein modifiziertes Muster von (\[([^][)({}]|\g<0>)*\])|\(\g<2>*\)|\{\g<2>*\}
Wenn Ihre Regex-Engine Rekursion unterstützt, schlage ich vor, 3 verschiedene Muster als Filter zu verwenden. Wenn Ihre Eingaben alle drei passieren, ist es eine gute Übereinstimmung - ([(?:[^][]|(?R))]) # match nested []
(((?:[^)(]|(?R)))) # match nested ()
({(?:[^{}]|(?R))*}) # match nested {}
Ich sehe nicht, wie Sie erwarten können, dass Ihre Regex mit Klammern übereinstimmt. Hier ist was deine Regex tut:
%Vor%