PHP String parsen

Hallo!

Ich habe einen langen String mit Text und HTML Tags. In diesem befindet sich auch folgendes :

<h2>Text</h2>

Gibt es eine schöne PHP Funktion mit der ich aus dem String den Text zwischen dem ersten <h2> auslesen kann ?
 
wobei "*?" keinen großen Sinn macht, oder?

.*? = (((beliebiges Zeichen) beliebig oft oder keinmal) einmal oder keinmal)

das Fragezeichen ist doch also überflüssig?


PHP:
<?php
$text = '<h1>foo</h1>
<h2>bar</h2>
<p>mooh</p>
<h2>bla</h2>
<p>blub</p>
';
if (preg_match_all('/<h2>(.*)<\/h2>/i', $text, $out)) {
    foreach ($out[1] as $i => $title) {
        echo 'Der ' . ($i+1) . '. H2-Titel lautet : ' . $title . '<br />' . chr(10);
    }
}
?>

wenn es dann natürlich wirklich drum geht, ineinander verschachtelte Elemente auszuwerten, dann kommst du mit regulären Ausdrücken nicht mehr weiter - dann musst du entweder selbst mit strpos, substr und co parsen oder eben dir schon erwähnte Projekte wie das von Christian Seiler oder den dort genannten Alternativen anschauen.
 
Doch, das Fragezeichen macht sehr wohl Sinn.
Wenn du dir die PCRE-Specs mal genauer anschaust, wirst du sehen, dass ein Fragezeichen nach einem Quantifier diesen von "greedy" nach "lazy" stellt, so dass der Quantifier nicht mehr die größtmögliche Zeichenmenge matcht, sondern die kleinstmögliche. Das ist wichtig, wenn du eine Sequenz von möglichen Matches hast. Ein Greedy-Quantifier matcht manchmal einfach zu viel:
Code:
preg_match_all('/<h2>(.*)<\/h2>/i', '<h2>Titel1</h2> ... <h2>Titel2</h2>', $out)
 --> 1 Match, $1 = 'Titel1</h2> ... <h2>Titel2'
preg_match_all('/<h2>(.*?)<\/h2>/i', '<h2>Titel1</h2> ... <h2>Titel2</h2>', $out)
 --> 2 Matches, erster Match: $1 = 'Titel1', 2. Match: $1 = 'Titel2'

Auch nachzulesen hier: http://de.php.net/manual/en/regexp.reference.repetition.php
However, if a quantifier is followed by a question mark, then it becomes lazy, and instead matches the minimum number of times possible, so the pattern /\*.*?\*/ does the right thing with the C comments. The meaning of the various quantifiers is not otherwise changed, just the preferred number of matches. Do not confuse this use of question mark with its use as a quantifier in its own right. Because it has two uses, it can sometimes appear doubled, as in \d??\d which matches one digit by preference, but can match two if that is the only way the rest of the pattern matches.

Deswegen: Lieber den Pattern (.*?) verwenden. Wenn die Tags weit auseinanderliegen, klappt es zwar mit (.*) oft genausogut, weil PHP per Default ein Linefeed (\n) nicht als '.' matcht (außer mit dem PCRE_DOTALL Modifier), aber sicher ist sicher.

mfg, metax.
 
@metax: thx. den Trick kannte ich noch nicht - dann nehm ich alles zurück und behaupte das Gegenteil ;)
ich handhabe das bisher auch wie mime mit dem Modifier U ...
 
Zurück
Oben