mit preg_match_all() ein- bzw. zweidimensionales Array erstellen

Parantatatam

mag Cookies & Kekse
Hallo,

ich bastle gerade an einer Template-Klasse. In dieser gibt es die Möglichkeit Sektionen, Variablen, Konstanten und Werte abhängig von ihrer Markierung im Template zu erstellen. Hauptsächlich geht es mir jetzt nur um das Problem mit den Sektionen und Werten. Werte können außerhalb von Sektionen existieren oder innerhalb von Sektionen. Dabei ist es nicht möglich Sektionen ineinander zu verschachteln. Ich habe schon eine Lösungsmöglichkeit parat mit der ich das Problem lösen könnte, aber diese frisst zu viele Ressourcen (FOREACH-Schleifen etc.). Jetzt habe ich mir überlegt, dass das doch auch direkt über RegEx in preg_match_ ... () umzusetzen möglich sein müsste.

Ein Beispiel:
Code:
{WERT1}{SECTION="sektion1"}{WERT2}{WERT3}{/SECTION}{WERT4}{SECTION="sektion2"}{WERT4}{/SECTION}{WERT5}
Das ergibt folgenden Array:
Code:
// Werte die nicht in Sektionen sind:
Array
(
    [WERT1] =>
    [WERT4] =>
    [WERT5] =>
)

// Werte in Sektionen:
Array
(
    [sektion1] => Array
        (
            [WERT2] =>
            [WERT3] =>
        )

    [sektion2] => Array
        (
            [WERT4] =>
        )

)

Für eine möglicherweise logischere Struktur wäre ich auch dankbar.
Also, wenn mir jemand helfen könnte, dann wäre ich ihm sehr dankbar.
 
Ich hoffe das hilft dir weiter.
PHP:
<?php

$str = '{WERT1}{SECTION="sektion1"}{WERT2}{WERT3}{/SECTION}{WERT4}{SECTION="sektion2"}{WERT5}{/SECTION}{WERT6}';
preg_match_all('/([{}a-z0-9]*){SECTION="sektion[0-9]{1,3}"}([{}a-z0-9]*){\/SECTION}({[a-z0-9]+})/is', $str, $matches);

array_pop($matches[1]);
$outer[] = array_merge($matches[1], $matches[3]);
echo '<hr><pre>';
print_r($outer);
echo '</pre>';

preg_match_all('/{[a-z0-9]*}/is', implode('', $matches[2]), $inner);
echo '<hr><pre>';
print_r($inner);
echo '</pre>';

?>

mit freundlichen Grüßen
Samuel Weber
 
Also die Sektionen müssen nicht den Wortstamm "sektion" enthalten die können auch "blub" oder "lol" oder was auch immer heißen, müssen sich nur an das Schema halten:
([A-Za-z_0-9 ])+

Und die Werte müssen sich nur an das Schema halten:
[A-Za-z]([A-Za-z0-9_])*

Das Problem bei deiner Idee ist, dass ich nicht die Namen der Sektionen erhalte, welche ich ja als Schlüsselwerte brauche.
 
Hallo,

mein Vorschlag wäre, sich zuerst alle {...} rauszugreifen, diese dann der Reihe nach durchzugehen und dabei das gewünschte Array aufzubauen. Das hat den Vorteil, dass man hier ggf. Fehlerbehandlung einfacher durchführen kann (im Beispielquelltext in Form einer Warnung) und einer Erweiterung auf geschachtelte Sektionen später auch nichts mehr im Weg steht.

Hier der Beispielquelltext:
PHP:
<?php

$str = '{WERT1}{SECTION="sektion1"}{WERT2}{WERT3}{/SECTION}{WERT4}{SECTION="sektion2"}{WERT4}{/SECTION}{WERT5}';

preg_match_all('/{(?:\/SECTION|SECTION="([A-Za-z_0-9 ]+)"|([A-Za-z](?:[A-Za-z0-9_])*))}/is', $str, $matches);

$num_matches = count($matches[0]);
$current_section = null;

$values = array();

for ($i = 0; $i < $num_matches; ++$i) {
	$section_name = $matches[1][$i];
	$value_name = $matches[2][$i];
	if ($value_name) {
		$values[$current_section][$value_name] = "";
	} elseif ($section_name) {
		if ($current_section != null) {
			echo "Warnung: geschachtelte Sektionen sind nicht erlaubt\n";
		}
		$current_section = $section_name;
	} else {
		if ($current_section == null) {
			echo "Warnung: {/SECTION} ohne vorheriges {SECTION=\"...\"}\n";
		}
		$current_section = null;
	}
}

print_r($values);

?>

Grüße, Matthias
 
Zurück