<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Brusdeylins &#187; RegEx</title>
	<atom:link href="http://brusdeylins.info/tag/regex/feed/" rel="self" type="application/rss+xml" />
	<link>http://brusdeylins.info</link>
	<description></description>
	<lastBuildDate>Wed, 28 Jul 2010 18:25:27 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Probleme mit ShortCodes</title>
		<link>http://brusdeylins.info/wordpress/probleme-mit-shortcodes/</link>
		<comments>http://brusdeylins.info/wordpress/probleme-mit-shortcodes/#comments</comments>
		<pubDate>Thu, 15 Jan 2009 17:08:22 +0000</pubDate>
		<dc:creator>Matthias Brusdeylins</dc:creator>
				<category><![CDATA[Wordpress]]></category>
		<category><![CDATA[Problem]]></category>
		<category><![CDATA[RegEx]]></category>
		<category><![CDATA[Regular Expression]]></category>

		<guid isPermaLink="false">http://neu.brusdeylins.info/?p=99</guid>
		<description><![CDATA[
Dies sieht sehr verd&#228;chtig nach einem Speicher-Problem aus. Doch wo genau tritt der Fehler auf und was kann man dagegen unternehmen? Ein kleiner Suchtrip durch den Quellcode von WordPress (zum Zeitpunkt dieses Artikels in der Version  2.7 ) zeigte bald, dass der Inhalt einer meiner langen Artikel in der Funktion wpautop() in der Datei [...]]]></description>
			<content:encoded><![CDATA[<p><!--:de-->
<a href="http://brusdeylins.info/media/post-images/wordpress.jpg" title="WordPress-Logo" rel="lightbox[singlepic37]" >
	<img class="ngg-singlepic ngg-right" src="http://brusdeylins.info/media/cache/37__150x400_wordpress.jpg" alt="WordPress-Logo" title="WordPress-Logo" />
</a>
Seid WordPress 2.5 bietet das Blogging-System seinen Erweiterungen (Plugins) die neue M&#246;glichkeit an,  mit so genannten <a title="ShortCode API" href="http://codex.wordpress.org/Shortcode_API" target="_blank">ShortCodes</a> Inhalte einfach und dynamisch zu modifizieren. Dazu muss eine Modifikations-Funktion auf einen entsprechenden ShortCode registriert werden, welcher dann automatisch aufgerufen wird. Ein ShortCode kann dabei noch zus&#228;tzliche Parameter definieren, die dann dieser Funktion zur Auswertung durchgereicht werden (Beispiel mit zwei Parameter: <code>[ShortCode Param1=Wert1 Param2=Wert2]</code>). Eines der ber&#252;hmtesten WordPress-Erweiterungen, welche in der neusten Version diese Technologie einsetzt, ist die Gallery-Verwaltung <a title="NextGEN Gallery at alex.rabe" href="http://alexrabe.boelinger.com/wordpress-plugins/nextgen-gallery/" target="_blank">NextGEN Gallery</a>. Und mit ihrem Einsatz f&#228;llt ein kleiner Fehler in WordPress auf: ShortCodes kombiniert mit sehr langen Beitr&#228;gen f&#252;hren bei der Anzeige gerne zu einem leeren Ergebnis.<!--:--><span id="more-99"></span><!--:de--></p>
<p>Dies sieht sehr verd&#228;chtig nach einem Speicher-Problem aus. Doch wo genau tritt der Fehler auf und was kann man dagegen unternehmen? Ein kleiner Suchtrip durch den Quellcode von WordPress (zum Zeitpunkt dieses Artikels in der Version  2.7 ) zeigte bald, dass der Inhalt einer meiner langen Artikel in der Funktion <code>wpautop()</code> in der Datei <em>./wp-includes/formatting.php</em> verloren ging. Und zwar genau in der vorletzte Zeile der Funktion:</p>
<pre>$pee = preg_replace('/&lt;p&gt;\s*?(' . get_shortcode_regex() . ')\s*&lt;\/p&gt;/s', '$1', $pee); // don't auto-p wrap shortcodes that stand alone</pre>
<p>(WordPress 2.7, Datei <em>formatting.php</em>, Funktion <code>wpautop()</code>, Zeile 153)</p>
<p>Diese Funktion sorgt daf&#252;r, dass vor der Ausgabe der Beitr&#228;ge Zeilenumbr&#252;che in HTML-Zeilenumbr&#252;che (<code>&lt;br /&gt;</code>) und HTML-Paragraphen (<code>&lt;p /&gt;</code>) umgewandelt werden. Sie wird vor der Ersetzung der ShortCodes aufgerufen. Die letzte Ersetzung sucht nun allein stehende ShortCodes und entfernt m&#246;gliche (automatisch hinzugef&#252;gte) Paragraphen um diese. Die hier aufgerufene Methode <code>get_shortcode_regex()</code> liefert dabei das Suchmuster f&#252;r die definierten ShortCodes zur&#252;ck. Diese befindet sich in der Datei <em>./wp-includes/shortcodes.php</em> ab der Zeile 165. Der hier zur&#252;ck gelieferte regul&#228;re Ausdruck sucht nach einem Muster in der folgenden Form:<br />

<a href="http://brusdeylins.info/media/post-images/shortcodes.jpg" title="Problem in Wordpress 2.7 RegEx - Bildquelle: Brusdeylins.Info" rel="lightbox[singlepic41]" >
	<img class="ngg-singlepic ngg-center" src="http://brusdeylins.info/media/cache/41__530x400_shortcodes.jpg" alt="WP 2.7 RegEx" title="WP 2.7 RegEx" />
</a>
In diesem Ausdruck werden zwei nicht-gierige (non-greedy, lazy) Quantoren eingesetzt. Dies bedeutet, es wird sehr viel Backtracking betrieben: die RegEx-Engine &#252;berspringt im ersten Schritt die Zeichen, welche auf solche nicht-gierigen Quantoren passen, da ja an dieser Stelle versucht wird, so wenig wie m&#246;glich einzufangen. Trotzdem merkt sich die Engine, wo sie notfalls nachschauen muss, falls der ganze restliche Text so erstmal nicht in das Suchmuster passt. Der &#8220;ganze Rest&#8221; bei gro&#223;en Beitr&#228;gen mit mehreren nicht-gierigen Quantoren kann ganz sch&#246;n viel sein, was die Historie gerne anwachsen l&#228;sst. Wir d&#252;rfen nicht vergessen: die RegEx-Engine geht am Ende nach und nach wieder ein Schritt zur&#252;ck und pr&#252;ft erneut nach, ob sie ein Ergebnis findet (Backtracking). Um den Aufwand zu minimieren, bietet es sich an, den zu &#252;berpr&#252;fenden &#8220;Rest&#8221; lokal einzuschr&#228;nken. In unserem Fall wird der Zeichenbereich der Parameterpaare mit dem Endzeichen &#8220;<code>]</code>&#8221; eines Tags begrenzt. &#196;ndern wir nun den roten Abschnitt <span style="color: #ff0000;"><code>(.*?)</code></span> zu <span style="color: #ff0000;"><code>([^\]]*?)</code></span>, trennen wir somit die Non-Greedy-Bereiche (Parameterpaare und m&#246;gliche Zwischeninhalte) und minimieren den Aufwand und somit den Speicherverbrauch. Unser &#252;berlanger Artikel m&#252;sste wieder erscheinen.</p>
<p>Mit einer kleine Sch&#246;nheitsoperation k&#246;nnen wir noch die (in meinen Augen) unn&#252;tze gr&#252;ne, nicht-einfangende Klammerung um den eingefangenen optionale Schr&#228;gstrich entfernen: <span style="color: #009000;"><code>(?:(\/))?</code></span> zu <span style="color: #009000;"><code>(\/)?</code></span>. Die modifizierte Methode <code>get_shortcode_regex()</code> sieht nun wie folgt aus:</p>
<pre>function get_shortcode_regex() {
    global $shortcode_tags;
    $tagnames = array_keys($shortcode_tags);
    $tagregexp = join( '|', array_map('preg_quote', $tagnames) );

    return '\[('.$tagregexp.')\b([^\]]*?)(\/)?\](?:(.+?)\[\/\1\])?';
}</pre>
<p>(WordPress 2.7, Datei <em>shortcodes.php</em>, Funktion <code>get_shortcode_regex()</code>, Zeile 165)</p>
<p>(Problems in Wordpress with long posts and plugins like NextGEN Gallery)<!--:--></p>
]]></content:encoded>
			<wfw:commentRss>http://brusdeylins.info/wordpress/probleme-mit-shortcodes/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>
