2009-09-20 7 views
0

J'essaie de faire correspondre un certain ensemble de balises dans un fichier modèle. Je veux cependant que les balises soient pouvant être imbriquées en elles-mêmes.PHP regex correspondant récursivement

Mon regex est le suivant: (avec/s)

<!-- START (.*?) -->(.*?)<!-- END \\1 --> 

exemple Tag:

<!-- START yList --> 
    y:{yList:NUM} | 
    <!-- START xList --> 
    x:{xList:NUM} 
    <!-- END xList --> 
    <!-- CARET xList --> 
    <br> 
<!-- END yList --> 
<!-- CARET yList --> 

En ce moment, les matchs résultat sera:

match de 0:

groupe (0) (Uniquement match)

<!-- START yList --> 
y 
<!-- START xList --> 
    x 
<!-- END xList --> 
<!-- CARET xList --> 
<br> 
<!-- END yList --> 
groupe

(1)

yList 
groupe

(2)

y 
<!-- START xList --> 
    x 
<!-- END xList --> 
<!-- CARET xList --> 
<br> 

Je veux 2 matchs au lieu de 1 évidemment, l'ensemble de balises imbriquées ne correspond pas. Est-ce possible avec regex, ou devrais-je garder les résultats de regexing group (2), jusqu'à ce que je n'ai trouvé aucun nouveau match?

Répondre

0

Vous pouvez faire quelque chose comme ceci:

$parts = preg_split('/(<!-- (?:START|END|CARET) [a-zA-Z][a-zA-Z0-9]* -->)/', $str, -1, PREG_SPLIT_DELIM_CAPTURE); 
$tokens = array(); 
$isTag = isset($tokens[0]) && preg_match('/^<!-- (?:START|END|CARET) [a-zA-Z][a-zA-Z0-9]* -->$/', $tokens[0]); 
foreach ($parts as $part) { 
    if ($isTag) { 
     preg_match('/^<!-- (START|END|CARET) ([a-zA-Z][a-zA-Z0-9]*) -->$/', $token, $match); 
     $tokens[] = array($match[1], $match[2]); 
    } else { 
     if ($token !== '') $tokens[] = $token; 
    } 
    $isTag = !$isTag; 
} 
var_dump($tokens); 

Cela vous donnera la structure de votre code.

5

Les expressions régulières ne sont pas adaptées à l'analyse de structures arborescentes de profondeur arbitraire. Cela peut être possible, en fonction de la saveur de regex que vous utilisez, mais ce n'est pas recommandé - ils sont difficiles à lire et difficiles à déboguer.

Je suggère d'écrire un simple analyseur à la place. Ce que vous faites est de décomposer votre texte dans un ensemble de possibles jetons qui peuvent chacun être définis par de simples expressions régulières, par exemple:

START_TOKEN = "<!-- START [A-Za-z] -->" 
END_TOKEN = ... 
HTML_TEXT = ... 

itérer sur votre chaîne, et aussi longtemps que vous regroupez ces jetons, les tirer hors de la chaîne, et les stocker dans une liste séparée. Assurez-vous de sauvegarder le texte qui était à l'intérieur du jeton (le cas échéant) lorsque vous faites cela. Ensuite, vous pouvez parcourir la liste de vos jetons et, en fonction des types de jetons, vous pouvez créer une structure arborescente imbriquée de nœuds, contenant chacun 1) le texte du jeton d'origine et 2) une liste de nœuds enfants. .

Vous pouvez regarder quelques tutoriels d'analyseur si cela semble trop compliqué.

+0

Intéressant. Pouvez-vous recommander des tutoriels d'analyse? –