Ruby - Regex für passende Klammern?
Ich versuche herauszufinden, ob ein string hat richtig geschlossen Klammern.
Dazu verwende ich die folgenden drei Klammerpaare.
[]
()
{}
Die Klammern können auch verschachtelt werden, solange Sie richtig formatiert.
)([]{} - Does not have properly closed brackets because )( is reverse order
[()] - Does contain properly closed brackets.
Habe ich versucht mit regex und nach ein wenig Fummelei, ich habe diese.
[^\(\[]*(\(.*\))[^\)\]]*
Allerdings gibt es ein paar Probleme mit diesem.
Es entspricht nur der Klammern, aber nicht mit Klammern
Ich verstehe nicht, warum es nicht passen die Klammern.
In meinen Beispielen habe ich deutlich verwendet einen backslash vor der Klammer.
Eingang
[] - true
[()] - true (nested brackets but they match properly)
{} - true
}{ - false (brackets are wrong direction)
}[]} - false (brackets are wrong direction)
[[]] - true (nested brackets but they match properly
- Wie wärs, wenn du uns zeigen, einige Eingänge und erwarteten Ausgänge.
- es ist unmöglich für regex . Sie müssen aktualisiert Ihre Frage mit diesem input
([][()]{}{{}[]})
- Sie sind absolut falsch.
- Warum......?
- Es ist möglich,.
- durch regex nur?
- Ja.
- Wo ist der regex? Meinst du deine regex?
- auch wenn möglich mit freaky rekursive Muster, Sie können nicht widersprechen, es ist sicherlich nicht eine gute Aufgabe für eine regex. Es kann durchgeführt werden in O(n) mit einem einfachen stack parser wie vorgeschlagen von Jeff Preis
- Das heißt ignoratio elenchi. Aber zumindest scheinen Sie zu wissen, besser als Avinash Raj.
- darüber will ich nicht streiten, es ist sicherlich unmöglich und nie. Nur wollten das Gespräch ein Hinweis in eine produktivere Richtung. Aber der Nachweis von einer reinen regex-Lösung (arbeiten mit rubys regex-engine) ist nicht überall in den Antworten, aber entweder.
- Alles was ich Tat wurde festgestellt, Menschen, die AvinashRaj Behauptung ist absolut falsch, so dass Sie nicht lernen, etwas falsch.
- die Sprache des strings mit passenden Klammern ist nicht regelmäßig. streng sprechen eine Sprache, die Erweiterung zu entsprechen, dies ist kein regulärer Ausdruck ist.
- Was ist Ihr plan für eine ausgewogene, aber falsch verschachtelte Zeichen? Zum Beispiel
balanced? '[{(])}'
im Allgemeinen true zurückgeben, es sei denn, du bist parsing-Grammatik. - Bitte Lesen Sie die Antworten. Ich geschrieben funktionierende Lösung basiert auf rekursiven regexp. Durch die Art und Weise, regex-Lösung in O(n) Zeit, wenn auch vielleicht mit größeren Konstante.
Du musst angemeldet sein, um einen Kommentar abzugeben.
freeze
angewendet wird, die Zeichenfolge wird nur generiert, wenn auch immer mal kann es gelesen werden.# frozen_string_literal: true
in der obersten Zeile von einer Datei in ruby 2.x, dies automatisch für alle string-Literale in die DateiDies ist wahrscheinlich eine schlechte Anwendungsfall für eine regex, würde ich eine einfache stack-parser.
edit: Cary Swoveland - schreiben code und haben Leute kritisieren :-?.
aktualisiert: Hatte einen fiesen kleinen bug in check, um zu sehen, wenn die schließende Zeichen übereinstimmen, wird die Eröffnung eines. fixed it!
Laut dieser Artikel, Ruby ab version 2.0 unterstützt rekursive regexps. Dies bedeutet, dass Sie verwenden können Ruby-spezifischen token
\g<0>
rekursiv match die ganze regexp-an jedem Punkt der regexp. Dieser Ansatz kann effektiv emulieren stack, um die zu lösen Ihre Aufgabe.Hier ist die resultierende regexp:
[^(){}\[\]]*(\((\g<0>)?\)|\{(\g<0>)?\}|\[(\g<0>)?\])?[^(){}\[\]]*
Diese aktualisierte version behandelt Fälle wie diese:
[(){}]
, wenn mehrere Klammer-Gruppen auf dem gleichen Niveau. Danke @Jonny 5 für den Hinweis auf diesen Fall:Dieser Ausdruck erfordert die Prüfung, wenn der gesamte Eingabestring verglichen wird. Teilweise übereinstimmung bedeutet, dass es es Fehler in Klammern die Bestellung an einem gewissen Punkt in der Zeichenfolge.
Hier ist die andere version, ist es nicht erforderlich zu prüfen, wenn die gesamte Eingabezeichenfolge wird abgestimmt:
Können Sie feststellen, dass es versucht, entsprechenden Paaren von Klammern und dann rekursiv Spiele selbst. Ich habe es ausprobiert hier und es scheint zu funktionieren. Ich bin nicht Ruby engineer, also ich kann nicht laufen eine tatsächliche Ruby test, aber ich hoffe, dass es nicht notwendig ist.
()
und verwenden\g<1>
statt\g<0>
."][" =~ r #=> 0
? Tut[^(){}\[\]]*
etwas zu tun?((.)(.))
nicht übereinstimmt oder sagen wir, es "passt" von Bedeutungtrue
.true
auch für([
. Er befasst sich nur mit so etwas wie(a[b])
aber nicht(a[b][b])
. Jedoch gab plus für die Erwähnung der Rekursion.r
gleich deine regex"][" =~ r #=> 0
, was bedeutet, dass"]["
spielen, beginnend bei offset0
, die es nicht sein sollte. Es ist die Abstimmung eine leere Zeichenfolge:"]["[r] #=> ""
.()
im())
und fast (?) gibt immertrue
. Was muss ich eingeben, dass es nicht zurücktrue
? Ich dachte, Sie sollten überprüfen, den gesamten string nach den gewünschten Regeln des OP und wenn die Zeichenfolge nicht gültig ist, nicht entsprechen, oder sagen wir: zurückfalse
.\A([^(){}\[\]]*((\((\g<1>)?\)|\{(\g<1>)?\}|\[(\g<1>)?\])?[^(){}\[\]]*)*)\Z
Ich nehme an, dein string besteht nur aus den Zeichen in der Zeichenfolge
"()[]{}"
. Beachten Sie, dass für einen stringstr
zu befriedigen, die passende Anforderung:str
muss leer sein oder eine unterzeichenfolge"()"
,"[]"
oder"[]"
; undstr
ist nicht-leer,str
mit"()"
,"[]"
und"[]"
entfernt, erfüllt die passende Voraussetzung.Deshalb können wir sequenziell entfernen substring Paare, bis wir nicht mehr tun. Wenn das, was Links leer ist, wird der original-string erfüllt die passende Voraussetzung; sonst ist es nicht:
regex ist nicht dazu gedacht, um zu validieren, die korrekte Grammatik in strings und dafür sehr schlecht geeignet für. Regex ist ein tool zum finden von mustern im text.
Sollten Sie einen parser verwenden.
Hier ist ruby-code für parser-stack zu tun, dass:
case
Anweisungen, um Ihren code besser Aussehen. AberStringScanner
effizienter wäre.char ==
syntax, die sieht im Grunde das gleiche, als wenn sonstEdit: verschoben zu den top-pro Jonny 5 Vorschlag
Nach dem Lesen der Kommentare unten, und inspiriert durch Aivean Lösung, hier ist eine modifizierte Muster
(\[([^][)({}]|\g<0>)*\])|\(\g<2>*\)|\{\g<2>*\}
wenn Ihr die regex-engine unterstützt Rekursion, schlage ich vor, 3 verschiedene Muster, die als Filter, wenn Sie Ihre Eingaben übergibt alle drei, es ist ein gutes Spiel
({)}
mit dieser, denke ich.Okay, ich dachte mir, diese.
Ich sehe nicht, wie könnten Sie erwarten, dass Ihre regulären Ausdruck für Klammer. Hier ist, was dein regex nicht: