preg_replace Problem – SELFHTML-Forum Forum als Ergänzung zum SELFHTML-Wiki und zur Dokumentation SELFHTML https://forum.selfhtml.org/self preg_replace Problem Wed, 30 Nov 16 10:19:32 Z https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681405#m1681405 https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681405#m1681405 <p>Hallo,</p> <p>ich scheiter gerade an einer regular expression Anweisung.</p> <p>Der Text ist wie folgt.</p> <pre><code class="block">TEXTTEXT {{ ZITAT 1 {{ ZITAT 2 }} }} ENDE TEXT </code></pre> <p>Nun soll das zwischen {{ und }} in einen DIV-Container gepackt werden.</p> <p>Meine Anweisung war wie folgt</p> <pre><code class="block">preg_replace("/{{([^\}\{]*)}}/i","<div class=\"quote\">$1</div>",$text); </code></pre> <p>aber ich bekomme nur einmal die "Klammer" ersetzt</p> <pre><code class="block">TEXTTEXT {{ ZITAT 1 <div class="quote"> ZITAT 2 </div> }} ENDE TEXT </code></pre> <p>eiegntlich sollte es so ausehen.</p> <pre><code class="block">TEXTTEXT <div class="quote"> ZITAT 1 <div class="quote"> ZITAT 2 </div> </div> ENDE TEXT </code></pre> <p>Wenn ich die Ausgabe zweimal hintereinander mache, klappt es, aber das kann ja nicht die Lösung sein, denn theoretisch könnte der Text 10 solcher Klammern haben - also brauche ich 10 mal diese replace Anweisung</p> <pre><code class="block">$text = preg_replace("/{{([^\}\{]*)}}/i","<div class=\"quote\">$1</div>",$text); $text = preg_replace("/{{([^\}\{]*)}}/i","<div class=\"quote\">$1</div>",$text); </code></pre> preg_replace Problem Wed, 30 Nov 16 10:28:51 Z https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681406#m1681406 https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681406#m1681406 <p>Tach!</p> <blockquote> <pre><code class="block">TEXTTEXT {{ ZITAT 1 {{ ZITAT 2 }} }} ENDE TEXT </code></pre> </blockquote> <p>Das sieht nach einem <a href="http://php.net/manual/en/regexp.reference.recursive.php" rel="noopener noreferrer">rekursiven Muster</a> aus.</p> <blockquote> <pre><code class="block">preg_replace("/{{([^\}\{]*)}}/i","<div class=\"quote\">$1</div>",$text); </code></pre> </blockquote> <p>Die geschweiften Klammern sind übrigens keine Sonderzeichen und müssen nicht maskiert werden.</p> <p>dedlfix.</p> preg_replace Problem Wed, 30 Nov 16 10:29:19 Z https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681407#m1681407 https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681407#m1681407 <p>Du suchst den Schnauzer? Oder <a href="http://rolfrost.de/jstemplates.html" rel="nofollow noopener noreferrer">das hier</a>, damit gehts auch ;)</p> preg_replace Problem Wed, 30 Nov 16 10:58:49 Z https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681409#m1681409 https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681409#m1681409 <p>@@mixmastertobsi</p> <blockquote> <pre><code class="block">TEXTTEXT {{ ZITAT 1 {{ ZITAT 2 }} }} ENDE TEXT </code></pre> <p>Nun soll das zwischen {{ und }} in einen DIV-Container gepackt werden.</p> </blockquote> <p>Ich sehe da zwei Fehler:</p> <ol> <li> <p><code>div</code>? Für Zitate ist <code>blockquote</code> (Block) bzw. <code>q</code> (Inline) da.</p> </li> <li> <p>Ein regulärer Ausdruck ist für solch einen Parser das falsche Werkzeug.</p> </li> </ol> <p>LLAP </p> <div class="signature">-- <br> <em>„Wenn du eine weise Antwort verlangst, musst du vernünftig fragen.“</em> —Johann Wolfgang von Goethe </div> preg_replace Problem Wed, 30 Nov 16 11:02:07 Z https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681411#m1681411 https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681411#m1681411 <p>Danke DIR!</p> <p>Kannst Du mal bitte ein Beispiel machen, wie es in meinem Beispiel aussehen müsste?</p> preg_replace Problem Thu, 01 Dec 16 11:10:56 Z https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681498#m1681498 https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681498#m1681498 <p>@mixmastertobsi @dedlfix</p> <p>Ein Problem mit solchen Fragestellungen ist auch immer, dass man erst mal definieren müsste, was bei <code>{{ foo }} bar }}</code> oder <code>{{ foo {{ bar }}</code> passieren soll.</p> preg_replace Problem Wed, 30 Nov 16 14:22:30 Z https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681438#m1681438 https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681438#m1681438 <blockquote> <p>Du suchst den Schnauzer? Oder <a href="http://rolfrost.de/jstemplates.html" rel="nofollow noopener noreferrer">das hier</a>, damit gehts auch ;)</p> </blockquote> <p>Hast du die richtige Seite verlinkt? Ich sehe da spontan keinen wirklichen Zusammenhang zur Fragestellung. :)</p> preg_replace Problem Wed, 30 Nov 16 11:01:32 Z https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681410#m1681410 https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681410#m1681410 <p>Hallo,</p> <p>das DIV war ja nur ein Beispiel. Kann gerne auch blockquote sein.</p> <p>Aber warum ist hier ein regulärer Ausdruck der falsche ANsatz?</p> preg_replace Problem Wed, 30 Nov 16 14:07:12 Z https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681437#m1681437 https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681437#m1681437 <p>Würde mich auch interessieren, welche fertige Library dafür geeignet ist. Wenn man es ohne Regex mit der Hand programmiert, wird es sicherlich fixer, aber auf jeden Fall ist der Code dann länger.</p> <p>Deine Regex funktioniert aber schlecht. Sollte</p> <pre><code class="block">TEXTTEXT {{ ZITAT 1 { ZITAT FORTSETZUNG }} ENDE TEXT </code></pre> <p>nicht</p> <pre><code class="block">TEXTTEXT <q> ZITAT 1 { ZITAT FORTSETZUNG </q> ENDE TEXT </code></pre> <p>ergeben? Tut es aber nicht.</p> <p>Ich habe es mal mit einer lookahead-Assertion versucht. Das Pattern matcht zuerst ein {{ und macht die Assertion, dass darauf kein weiteres {{ folgt. Dann matcht es beliebige Zeichen, aber non-greedy, und ein }}. Der non-greedy Match sorgt dafür, dass .* bei einem geschachtelten Zitat das innere }} nicht einschließt.</p> <p>Das ganze legst Du in eine Schleife und machst es so lange, wie etwas ersetzt wird. Die Spielerei mit $i soll nur anzeigen, in welcher Reihenfolge er die Zitate ersetzt. Das musst Du natürlich für den realen Einsatz entfernen.</p> <pre><code class="block language-php"><span class="token variable">$text</span> <span class="token operator">=</span> <span class="token string double-quoted-string">"TEXTTEXT {{ ZITAT 1 {{ ZITAT 2 }} Z1 }} {{ ENDE }} TEXT"</span><span class="token punctuation">;</span> <span class="token variable">$i</span><span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">;</span> <span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token constant boolean">true</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$textNeu</span> <span class="token operator">=</span> <span class="token function">preg_replace</span><span class="token punctuation">(</span><span class="token string double-quoted-string">"//{{(?!.*{{)(.*?)}}/i"</span><span class="token punctuation">,</span><span class="token string double-quoted-string">"<q_<span class="token interpolation"><span class="token variable">$i</span></span>><span class="token interpolation"><span class="token variable">$1</span></span></q_<span class="token interpolation"><span class="token variable">$i</span></span>>"</span><span class="token punctuation">,</span><span class="token variable">$text</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$text</span> <span class="token operator">===</span> <span class="token variable">$textNeu</span><span class="token punctuation">)</span> <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token variable">$text</span> <span class="token operator">=</span> <span class="token variable">$textNeu</span><span class="token punctuation">;</span> <span class="token variable">$i</span><span class="token operator">++</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">echo</span> <span class="token variable">$text</span><span class="token punctuation">;</span> </code></pre> <p>Eine Lösung ohne Regex wäre wohl ein handgemachter Parser, der von links nach rechts durchgeht und einen Quote-Stack bildet, oder die Nutzung einer PHP Library, die ich nicht kenne.</p> <p><em>Rolf</em></p> preg_replace Problem Wed, 30 Nov 16 11:07:01 Z https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681413#m1681413 https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681413#m1681413 <p>Tach!</p> <blockquote> <p>Kannst Du mal bitte ein Beispiel machen, wie es in meinem Beispiel aussehen müsste?</p> </blockquote> <p>Nee, kann ich nicht. Ich weiß nur, dass das dafür gedacht ist und hab es dir als Stichwort zur weiteren konkreten Recherche geliefert.</p> <p>dedlfix.</p> preg_replace Problem Sat, 03 Dec 16 13:27:59 Z https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681650#m1681650 https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681650#m1681650 <p>Hallo mixmastertobsi,</p> <blockquote> <p>Kannst Du mal bitte ein Beispiel machen, wie es in meinem Beispiel aussehen müsste?</p> </blockquote> <p>Da du ja ersetzen möchtest (nicht nur die äußerste Ebene finden), wird <code>preg_replace</code> mit einem <a href="http://www.rexegg.com/regex-recursion.html" rel="nofollow noopener noreferrer">rekursiven regex</a> nicht ausreichen. Das rekursive Suchmuster ermöglicht es, die äusserste Ebene zu finden, es ist aber afaik nicht möglich, in jedem Selbstaufruf mit dem <a href="http://www.regular-expressions.info/brackets.html" rel="nofollow noopener noreferrer">captured match</a> zu ersetzen.</p> <p>1.) Nun könntest du per <a href="http://php.net/manual/de/function.preg-replace-callback.php#example-5268" rel="noopener noreferrer"><code>preg_replace_callback</code> (siehe Beispiel)</a> von aussen nach innen auflösen.</p> <pre><code class="block language-php"><span class="token keyword">function</span> <span class="token function-definition function">parse_recursive</span><span class="token punctuation">(</span><span class="token variable">$inp</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">is_array</span><span class="token punctuation">(</span><span class="token variable">$inp</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token variable">$inp</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'<div class="quote">'</span><span class="token operator">.</span><span class="token variable">$inp</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token operator">.</span><span class="token string single-quoted-string">'</div>'</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token function">preg_replace_callback</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/{{((?>[^}{]+|(?R))*)}}/'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'parse_recursive'</span><span class="token punctuation">,</span> <span class="token variable">$inp</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> <p><a href="https://eval.in/690337" rel="nofollow noopener noreferrer">Hier ein Beispiel auf eval.in</a> und das <a href="https://regex101.com/r/dVRTPN/1" rel="noopener noreferrer">Suchmuster auf regex101</a> zum probieren.</p> <p>2.) Oder wie schon angesprochen per <code>preg_replace</code> und <code>while</code> von innen nach aussen.</p> <pre><code class="block language-php"><span class="token variable">$regx</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'/{{([^}{]+)}}/'</span><span class="token punctuation">;</span> <span class="token variable">$repl</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'<div class="quote">$1</div>'</span><span class="token punctuation">;</span> <span class="token keyword">while</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token variable">$tmp</span> <span class="token operator">=</span> <span class="token function">preg_replace</span><span class="token punctuation">(</span><span class="token variable">$regx</span><span class="token punctuation">,</span> <span class="token variable">$repl</span><span class="token punctuation">,</span> <span class="token variable">$str</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">!==</span> <span class="token variable">$str</span><span class="token punctuation">)</span> <span class="token variable">$str</span> <span class="token operator">=</span> <span class="token variable">$tmp</span><span class="token punctuation">;</span> </code></pre> <p>Noch ein <a href="https://eval.in/690331" rel="nofollow noopener noreferrer">Beispiel auf eval.in</a></p> <p>Würde eher zu Variante 2 tendieren. Viel Erfolg, Robert</p> preg_replace Problem Thu, 01 Dec 16 11:22:02 Z https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681499#m1681499 https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681499#m1681499 <p>Tach!</p> <blockquote> <p>Ein Problem mit solchen Fragestellungen ist auch immer, dass man erst mal definieren müsste, was bei <code>{{ foo }} bar }}</code> oder <code>{{ foo {{ bar }}</code> passieren soll.</p> </blockquote> <p>Garbage in, garbage out - wäre eine Strategie, den Verwender in die Pflicht zu nehmen, Ordentliches zu liefern, wenn er Ordentliches zurückhaben möchte. Wenn man solche Fehler finden möchte, wird man mit Regex nicht weiterkommen. Da muss dann ein Parser ran, der in der Lage ist, ungültige Syntax zu erkennen. Das ist letzlich eine Frage von Aufwand und Nutzen unter Berücksichtigung des Ziels, ob der einfache Regex reicht oder ob es ein komplexer Parser sein muss.</p> <p>dedlfix.</p> preg_replace Problem Thu, 01 Dec 16 11:47:11 Z https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681500#m1681500 https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681500#m1681500 <p>@@dedlfix</p> <blockquote> <p>Garbage in, garbage out - wäre eine Strategie</p> </blockquote> <p>Oft ist Garbage in, error message out die bessere.</p> <p>LLAP </p> <div class="signature">-- <br> <em>„Wenn du eine weise Antwort verlangst, musst du vernünftig fragen.“</em> —Johann Wolfgang von Goethe </div> preg_replace Problem Thu, 01 Dec 16 12:50:55 Z https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681513#m1681513 https://forum.selfhtml.org/self/2016/nov/30/preg-replace-problem/1681513#m1681513 <p>Tach!</p> <blockquote> <blockquote> <p>Garbage in, garbage out - wäre eine Strategie</p> </blockquote> <p>Oft ist Garbage in, error message out die bessere.</p> </blockquote> <p>Oft ist es besser, nicht ohne Anwendungsfall die Strategien zu bewerten (=> anwendungsfallorientiert statt strategieorientiert).</p> <p>dedlfix.</p>