2016-06-01 7 views
3

Ich muss erkennen, ob eine Zeichenfolge enthält nicht geschlossene spitze Klammern.PHP regexp - Detected nicht geschlossene Klammern

versuchte ich regulären Ausdruck durch Vergleich Anzahl der linken und rechten Klammern zu vermeiden:

if (substr_count($string, '<') !== substr_count($string, '>')) 
{ 
    // Text contains unclosed angle brackets   
} 

Aber diese Methode erkennt nicht, wie dieser Fehler:

This is >b<BOLD>/b< word 
+0

ist es html? dann könnten Sie das versuchen: http://stackoverflow.com/questions/3167074/which-function-in-php-validate-i-f-the-string-is-valid-html – jbe

+0

Überprüfen Sie bitte die Antworten und erwägen, das eine zu akzeptieren funktioniert am besten für Sie/Upbooten diejenigen, die Sie hilfreich finden. Oder geben Sie weitere Klarstellungen im Hauptteil Ihrer Frage an. –

Antwort

2

Ich würde nicht empfehlen, reguläre Ausdrücke für eine Aufgabe wie diese zu verwenden.
Eine einfache Funktion eine Zeichenfolge für richtig geschrieben Klammern zu prüfen ist schnell geschrieben:

/** 
* @param $str input string 
* @returns boolean true if all brackets are properly opened and closed, false otherwise 
*/ 
function checkBraces($str) 
{ 
    $strlen = strlen($str); // cache string length for performance 
    $openbraces = 0; 

    for ($i = 0; $i < $strlen; $i++) 
    { 
     $c = $str[$i]; 
     if ($c == '<') // count opening bracket 
      $openbraces++; 
     if ($c == '>') // count closing bracket 
      $openbraces--; 

     if ($openbraces < 0) // check for unopened closing brackets 
      return false; 
    } 

    return $openbraces == 0; // check for unclosed open brackets 
} 

Mit diesem Code als Grundlage, ist es nicht allzu schwierig sein, sollte eine Überprüfung, um zu überprüfen, ob der Tag-Name zu implementieren Öffnungs- und Schließbügel passt auch - aber das werde ich Ihnen überlassen :-)

+0

* "Ich würde die Verwendung von regulären Ausdrücken für eine Aufgabe wie diese nicht empfehlen." * Aus welchem ​​Grund? –

+0

* "Eine einfache Funktion, um eine Zeichenfolge für richtig geschriebene Klammern zu überprüfen, wird schnell geschrieben" * und langsamer auszuführen. –

+0

@CasimiretHippolyte die Anwendbarkeit von regulären Ausdrücken auf HTML und ähnliche Sprachkonstrukte wurde unzählige Male auf dieser Website diskutiert, ich bin sicher, dass Sie diese Threads finden können. Wenn die Leistung ein Problem für Sie ist, ist PHP das falsche Werkzeug, um damit zu beginnen. –

2

Aber diese Methode wird nicht Fehler wie folgt erkennen:

Weil das Zählen macht Sinn nur dann, wenn Sie prüfen möchten, ob die Anzahl der öffnenden und schließenden Klammern gleich ist. Aber wenn Sie freundlich zu Ihrem Benutzer sein und auf den Ort zeigen möchten, an dem er einen Fehler gemacht hat, dann ist das Zählen nicht ausreichend und Sie sollten den Stack verwenden (sogar Array-basierter Stack basierend auf array_push() und array_pop() würde ausreichen). Mit stack iterieren Sie über Ihre Zeichenfolge und drücken ein Token, wenn Sie die öffnende Klammer < treffen und ein Token aufstoßen, wenn Sie ein > schließen. In Ihrem Fall:

This is >b<BOLD>/b< word 

würden Sie pop als erstes zu tun haben, ist > aber es gibt nichts auf Stapel so löst dieser Fehler. Lassen Sie sich, dass die Halterung befestigen und weiter:

This is <b<BOLD>/b< word 

und läuft

push -> ok 
push -> well if you allow nested brackets, then all is ok, otherwise 
     stack must be empty prior pushing so this bracket is misplaced 
     and you shall throw an error 

und so weiter ... und wenn Sie Ende der Schnur zu erreichen und der Stapel nicht leer ist, dann wissen Sie entdeckten letzte < Misses sein > Paar (Wenn Sie Bracket verschachteln, dann Logik möglicherweise zu sagen, welche möglicherweise nicht geschlossen ist möglicherweise komplizierter und manchmal falsche Ergebnisse (wie Compiler manchmal in einem ähnlichen Fall zum Beispiel)).

Wenn Sie keine verschachtelten Klammern planen zu lassen, dann können Sie Ihren Code machen noch einfacher als einfachen integer Variable mit dem Zustand, um anzuzeigen, würde genügen (dh ‚0‘ für <, 1 für > und -1 für den Ausgangszustand)

1

Schleife durch die Zeichenfolge um jeweils ein Zeichen, wenn das Zeichen ein "<" ist, inkrementiere einen Zähler, und wenn es ">" ist, dekrementiere den Zähler. Wenn der Zähler jemals negativ wird oder der Zähler nicht Null ist, wenn Sie die Zeichenfolge durchlaufen, haben Sie Klammern geschlossen.

+0

'dann haben Sie nicht geschlossene Klammern, aber Sie wissen immer noch nicht wo. –

+0

Die Frage war nur zu erkennen, ob es nicht geschlossene Klammern gibt, nicht wo sie sind. – Schleis

1

Es gibt eine PCRE regex für eine korrekte Anzahl von symmetrischen spitzen Klammern zu überprüfen:

'~\A[^<>]*+(<(?>[^<>]|(?1))*+>[^<>]*+)++\z~' 

Siehe regex demo

Weitere Informationen finden Sie unter der Matching Balanced Constructs Seite bei regular-expressions.info.

Kurz:

  • \A - Beginn der Zeichenfolge
  • [^<>]*+ - null oder mehr Zeichen andere als < und >
  • (<(?>[^<>]|(?1))*+>[^<>]*+)++-1 oder mehrere Vorkommen von
    • < - Eröffnung < Klammer
    • (?>[^<>]|(?1))*+ - 0 oder mehr beliebige char außer < und > (siehe [^<>]) oder die gesamte Gruppe 1 Submuster (der Subroutinenaufruf (?1))
    • > - Schließ > Halterung
    • [^<>]*+ - null oder mehr Zeichen anderer als < und >
  • \z - Ende der Zeichenfolge.
-1

Hier ist eine Regex, die verschachtelte Klammern nicht zulässt.

/^([^<>]*<[^>]*?>[^<>]*)*$/m