Robert R.: PCRE Pattern für Klammerebenen gesucht

Liebe Wissende,

ich suche nach einer Möglichkeit, Klammerebenen zu erkennen und zu trennen.

Beispiel:

viel Text drumherum
    [abc, 12
       [345]
       [yxz]
    ] noch mehr Kot danach
    auch noch in der nächsten Zeile
    [weiter]
    und Ende

soll auseinandergenommen werden zu

--+-- [abc, 12 --+--[345]
  |      [345]   |
  |      [yxz]   +--[yxz]
  |   ]
  |
  |
  +-- [weiter]

Es sollen also nur die Klammerausdrücke extrahiert werden und wenn sie unterebenen enthalten, diese auch gefunden werden

Kann man sowas mit PCRE schaffen, eventuell auch mehrstufig, also als rekursive Funktion?

Danke für Tipps

Robert

  1. Tach!

    ich suche nach einer Möglichkeit, Klammerebenen zu erkennen und zu trennen.
    Kann man sowas mit PCRE schaffen, eventuell auch mehrstufig, also als rekursive Funktion?

    Soweit ich weiß, ja. PCRE hat eine recht umfangreiche Dokumentation im PHP-Handbuch und wenn ich mich recht erinnere, musst du da nach rekursivem Muster suchen.

    dedlfix.

    1. Lieber Dedlfix,

      ich suche nach einer Möglichkeit, Klammerebenen zu erkennen und zu trennen.
      Kann man sowas mit PCRE schaffen, eventuell auch mehrstufig, also als rekursive Funktion?

      Soweit ich weiß, ja. PCRE hat eine recht umfangreiche Dokumentation im PHP-Handbuch und wenn ich mich recht erinnere, musst du da nach rekursivem Muster suchen.

      Danke schon mal. Habe ich auch gerade entdeckt. Kann ich aber leider noch nicht mit umgehen. Ich schlage mich gerade mit den Backreferenzen bzw. Teiltreffern eines Musters rum. Hierzu auch noch eine Frage:

        
          (-([0-9]+))?  
        
      
      

      das soll bewirken, dass aus einem größeren Muster

        
       Blah77-Blue4you-ABC-01-xyz  
        
      
      

      die 01 (oder eine andere Ziffernfolge an dieser Stelle) herausgefiltert werden kann, wenn sie da ist. Ich möchte aber das "-" nicht als Backreferenz haben. Für das Muster ist es aber notwendig. Ich erinnere mich, dass man die Aufnahme in die Backreferenzen unterdrücken konnte. Oder irre ich mich da?

      Grüße

      Robert

      1. Liebe Wissende,

        Ich schlage mich gerade mit den Backreferenzen bzw. Teiltreffern eines Musters rum. Hierzu auch noch eine Frage:

        (-([0-9]+))?

        
        >   
        > das soll bewirken, dass aus einem größeren Muster  
        >   
        > ~~~php
          
        
        >  Blah77-Blue4you-ABC-01-xyz  
        >   
        > 
        
        

        die 01 (oder eine andere Ziffernfolge an dieser Stelle) herausgefiltert werden kann, wenn sie da ist. Ich möchte aber das "-" nicht als Backreferenz haben. Für das Muster ist es aber notwendig. Ich erinnere mich, dass man die Aufnahme in die Backreferenzen unterdrücken konnte. Oder irre ich mich da?

        Habe da was gefunden, was auch scheinbar funktioniert:

          
            (?>-([0-9]+))?  
          
        
        

        Ist das hier richtig angewandt? Es tut jedenfalls das, was ich will.

        Grüße

        Robert

  2. Liebe Wissende,

    ich habe mir jetzt eine rekursive Funktion dafür gestrickt.
    Vielleicht habt Ihr eine Idee, wie man die noch vereinfachen/verbessern kann?

      
    function get_parts ($tpl)  
    {  
    	$_parts = array();  
      
    	$open = 0;  
    	$close = 0;  
    	$pos = 0;  
    	$len = strlen($tpl);  
    	$start = 0;  
    	  
    	  
    	while (($len > 0) && ($pos < $len))  
    	{  
    	    if ($tpl[$pos] == '[')  
    		{  
    			$open++;  
      
    			if ($open == 1)  
    			{  
    				$start = $pos;  
    			}	  
    		}  
    		  
    		if ($tpl[$pos] == ']')  
    		{  
    		    $close++;  
    		}  
    				  
                    if (($open == $close) && ($open > 0))  
    		{  
    			$str = substr($tpl, $start +1, $pos - $start -1);	  
    			$_parts[$str] = get_parts($str);  
      
                            if (count($_parts[$str]) == 0)  
    			{  
    				$_parts[$str] = evaluate($str);  
    			}  
    			  
    			$tpl = substr($tpl, $pos +1);  
    			$len = strlen($tpl);	  
      
    			$open = 0;  
    			$close = 0;  
    			$pos = 0;  
    			$start = 0;  
    		}	  
    		else  
    		{  
    			$pos++;  
    		}  
    	}  
    	  
            return $_parts;  
    }  
      
    
    

    Grüße

    Robert

  3. @@Robert R.:

    nuqneH

    An sowas wie

    viel Text drumherum
        [abc, "]"
           [345]
           [yxz]
        ] noch mehr Kot danach

    hast du gedacht? Nicht dass dir dein Parser unerwartete Ergebnisse liefert oder du gar Sicherheitslöcher aufreißt.

    Qapla'

    --
    „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
    1. Lieber Wissender Gunnar,

      hab Dank für den Hinweis.

      An sowas wie

      viel Text drumherum
          [abc, "]"
             [345]
             [yxz]
          ] noch mehr Kot danach

      hast du gedacht? Nicht dass dir dein Parser unerwartete Ergebnisse liefert oder du gar Sicherheitslöcher aufreißt.

      Ist nicht vorgesehen, da die Klammern im übrigen Zeichensatz nicht vorkommen können. Sie werden dort ersetzt durch die Codesequenzen &#91; und &#93;

      Grüße
      Robert

  4. Hallo Robert,

    ich suche nach einer Möglichkeit, Klammerebenen zu erkennen und zu trennen.

    Ein rekursives Suchmuster ist in PCRE möglich. Für die äußerste Ebene könnte es z.B. so aussehen:

    \[(?:[^][]|(?R))*\]  
    
    

    Findet eine öffnende eckige Klammer, gefolgt von
    (einem Zeichen, das keine eckige Klammer ist | ODER fügt das Suchmuster an der Stelle(?R) ein)
    * beliebig oft. Gefolgt von einer schließenden eckigen Klammer.

    (?: leitet eine sog. Non-capturing group ein. Hier wäre auch eine sog. Atomic group möglich.

    Anstatt (?R) könnte man auch (?0) notieren. 0 Bezieht sich auf das gesamte Suchmuster (?1) wäre wenn vorhanden das erste umklammerte Teilmuster usw.

    lG, Robert