Aller au contenu

[PHP] PCRE récalcitrant


FJA
 Share

Messages recommandés

Salut,

 

Voilà dans une chaîne je cherche a extraire une séquence bien particulière.

Seulement voilà, cette séquence peut être inclue dans une autre séquence du même type. Donc ce que veux faire c'est récupéré la plus petite séquence possible, la stocker, la remplacé par une chaîne repère et recommencer jusqu'à ce que la séquence n'apparaît plus dans mon texte initial.

 

En théorie tout fonctionne, mais en théorie seulement.

Dans mon code il y a quelque chose qui doit m'échapper.

 

Voici le code que j'utilise

<?php
class MaClass
{
var $Sequence = Array();

function Recherche(&$Texte, $Tour=0)
{
	//C'est la séquence a rechercher
	$Find = '/<Debut:(.[^>]+)>(.+)<Fin>/Us';

	preg_match_all($Find, $Texte, $Match, PREG_SET_ORDER);

	if(count($Match) == 0) { return($Texte); }

	foreach($Match As $Valeur)
	{
		$this->Sequence[$Tour] = Array('SeqText' => $Valeur[0], 'Variable' => $Valeur[1]);

		$Texte = str_replace($Valeur[0], '<#Seq-'.$Tour.'#>', $Texte);
		$Tour++;
	}

	$this->Recherche(&$Texte, $Tour);
}
}

//C'est le texte dans lequel il y a une rechrecher
$Texte = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor. <Debut:FisrtOne>Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor<Debut:Second>, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat. Duis semper. Duis arcu massa, scelerisque vitae, consequat in<Fin>, pretium a, enim.<Fin> Pellentesque congue. Ut in risus volutpat libero pharetra tempor. Cras vestibulum bibendum augue. Praesent egestas leo in pede. Praesent blandit odio eu enim. Pellentesque sed dui ut augue blandit sodales. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aliquam nibh. Mauris ac mauris sed pede pellentesque fermentum. Maecenas adipiscing ante non diam sodales hendrerit';

$MaClassMoi = new MaClass();

$MaClassMoi->Recherche(&$Texte);

print_r($MaClassMoi->Sequence);
?>

 

Array

(

[0] => Array

(

[seqText] => <Debut:FisrtOne>Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor<Debut:Second>, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat. Duis semper. Duis arcu massa, scelerisque vitae, consequat in<Fin>

[Variable] => FisrtOne

)

 

)

 

Le problème c'est que normalement il devrait d'abords trouver <Debut:Second>, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat. Duis semper. Duis arcu massa, scelerisque vitae, consequat in<Fin>

Et ensuite <Debut:FisrtOne>Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor<#Seq-0#>, pretium a, enim.<Fin>

Seulement il prend le 1er <Debut:…> et le 1er <Fin>

 

SERVER_SOFTWARE = Apache/1.3.33 (Unix) PHP/5.1.2

 

@Toute

Lien vers le commentaire
Partager sur d’autres sites

Alors 2 points :

- preg_match_all, comme la plupart pour ne pas dire toutes les fonctions utilisant les regex (et tous les moteurs de RegEx), recherche les chaînes dans l'ordre de parcours normal (de gauche à droite, sauf backward-references ou cas particuliers du genre). Donc c'est tout à fait normal qu'il trouve FirstOne avant Second

- De plus puisque tu utilises preg_match_all, il te trouve directement toutes les occurences, y compris les occurences imbriquées. Tu n'as donc besoin que d'un seul passage.

 

Et pour finir, tu te mélanges les pinceaux je pense sur ta répétition : tu fais à la fois un foreach pour parcourir toutes les occurences trouvées (les imbriquées et les non-imbriquées)... et en plus tu utilises la recursivité poru refaire appel à ta fonction... alors que toutes les occurences ont déjà été remplacées !

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

Le faite que j'utilise preg_match_all n'est pas anodin : mon texte peut contenir plusieurs séquences sur le même niveau, et donc preg_match_all avais pour but d'avoir le plus d'occurrence possible.

 

Sinon pour faire fonctionner ma fonction, preg n'est pas la bonne solution?

Tu as quelque chose à me proposé?

 

@Toute

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

Je vous fait part de la solution que j'ai choisi pour faire ce que je voulais:

  1. Je cherche la première occurrence de la balise fermante grâce à strpos
  2. Je créé un segment de mon texte qui va du début jusqu'à l'Offset (position) de la balise fermante précédemment trouver avec la fonction substr
  3. Je cherche la dernière occurrence de la partie fixe de la balise ouvrante grâce à strrpos dans le segment précédemment créé
  4. J'extrait les informations (le nom de la variable) grâce à preg_match dans l'extrait qui se trouve entre les deux balises (via substr et les Offsets des balises)
  5. Je remplace ma séquence par un identifiant dans mon texte initial avec la fonction substr_replace
  6. Et pour finir je recommence l'opération dans le nouveau texte fraîchement créé jusqu'à ce que les étapes 1 ou 3 ne trouve rien

 

Vous verrez bientôt a quoi ce code a bien pu servir (maintenant il ne me reste plus l'aide a finir…)

 

 

@Toute

Lien vers le commentaire
Partager sur d’autres sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Invité
Répondre à ce sujet…

×   Collé en tant que texte enrichi.   Coller en tant que texte brut à la place

  Seulement 75 émoticônes maximum sont autorisées.

×   Votre lien a été automatiquement intégré.   Afficher plutôt comme un lien

×   Votre contenu précédent a été rétabli.   Vider l’éditeur

×   Vous ne pouvez pas directement coller des images. Envoyez-les depuis votre ordinateur ou insérez-les depuis une URL.

Chargement
 Share

×
×
  • Créer...