IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Optimiser/"factoriser" un masque regex


Sujet :

Langage PHP

  1. #1
    Invité
    Invité(e)
    Par défaut Optimiser/"factoriser" un masque regex
    Bonjour,
    pour mes Fonctions de troncature de texte, j'ai besoin d'optimiser, si possible, une regex :
    => si les points de suspension sont après une(des) balise(s) fermante(s),
    on les "remonte" jusqu'à l'intérieur de la balise non-vide la plus proche (ici jusqu'à 5 niveaux de balises).

    Voici mon masque actuel :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    	$PointSuspension 	= '...';
    	$texte	.= 'ReplacePointSuspension'; // (provisoire)
    	$pattern	= '#((</[^>]*>[\n\t\r ]*)?(</[^>]*>[\n\t\r ]*)?(</[^>]*>[\n\t\r ]*)?(</[^>]*>[\n\t\r ]*)?(</[^>]*>)[\n\t\r ]*ReplacePointSuspension)#i';
    	// Explication du masque : ((</[^>]*>[\n\t\r ]*)?
    	// </[^>]*>	: toute balise fermante
    	// [\n\t\r ]*	: passage(s) à la ligne/tabulation(s)/espace(s)
    	$texte	= preg_replace($pattern, $PointSuspension.'${2}${3}${4}${5}${6}', $texte);
    Exemple :
    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <ul>
      <li>sdg sdfg sdfgsd</li>
      <li></li>
    </ul>
    ...
    donne :
    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    <ul>
      <li>sdg sdfg sdfgsd</li>
      <li>...</li>
    </ul>

    Question :
    • Est-il possible de "factoriser" les (</[^>]*>[\n\t\r ]*)? ? (les 4 premiers du masque, le 5ème étant requis)
    • Tout en récupérant '${2}${3}${4}${5}${6}' (ou quelle autre syntaxe ?)


    Merci !

  2. #2
    Membre émérite Avatar de tsuji
    Inscrit en
    Octobre 2011
    Messages
    1 558
    Détails du profil
    Informations forums :
    Inscription : Octobre 2011
    Messages : 1 558
    Points : 2 736
    Points
    2 736
    Par défaut
    Les niveaux de balises ne devraient pas un problème: c'est surmontable. Ce que je veux rajouter comme éléments de considération:

    [1] Que de permettre la balise dit vide d'avoir d'attributs: c'est plus conformant aux recommendations de xml; et

    [2] Qu'une balise dit vide puisse s'écrire de deux façons equivalentes.

    Avec ça, le script serait plus conformant aux cas réels et aux recommendations de xml.

    Je propose ceci qui marche pour des cas j'ai considérés.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    //$texte étant donnée
     
    $exp1="((<(([^\s>]+)(\s+[^>]*)?))>)"."(</\\5>)";    //compte 4 + un englobant = 5
    $exp2="(<(([^\s/>]+)(\s[^>]*)?))/(>)";
    $exp3="((\s*</[^>]+>\s*)*)";
    $PointSuspension='(\.{3,})';
     
    $exp="(".$exp1."|".$exp2.")";
     
    $pattern="#".$exp.$exp3.$PointSuspension."#";
     
    $replacement='<$4$9>${15}</$5${10}>${13}';
    $t=preg_replace($pattern, $replacement, $texte);
     
    echo $texte,"\n";
    echo $t,"\n";
    Pour un échantillon typique, vous pouvez prendre ça pour l'instant.
    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <root>
        <x>abc
            <y attr="y">
                <z>
                    <p>
                        <q a="q"></q>
                    </p>
                </z>
            </y>
        </x>...
        <x>stu
            <y attr="y2">
                <p>
                    <q a="q2" />
                </p>
            </y>
        </x>...
    </root>

  3. #3
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    et merci pour ton aide.

    Mais je ne cherche pas à remonter les "..." dans une balise vide, mais dans la dernière qui contient du texte.
    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <root>
        <x>AAAA
            <y attr="y">
                <z>BBBB
                    <p>
                        <q a="q"></q>
                    </p>
                </z>CCCC
            </y>
        </x>
    </root>...
    donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <root>
        <x>AAAA
            <y attr="y">
                <z>BBBB
                    <p>
                        <q a="q"></q>
                    </p>
                </z>CCCC...
            </y>
        </x>
    </root>
    Je n'ai pas besoin des balises ouvrantes (donc pas besoin d'attributs)

    Seules les balises fermantes sont prises en compte,
    à partir des "..." et en remontant jusqu'à la balises non-vide (contenant du texte).

  4. #4
    Membre émérite Avatar de tsuji
    Inscrit en
    Octobre 2011
    Messages
    1 558
    Détails du profil
    Informations forums :
    Inscription : Octobre 2011
    Messages : 1 558
    Points : 2 736
    Points
    2 736
    Par défaut
    Bonjour, si les balises de type 'mixed' peuvent parître comme ça, il suffit de remplacer $exp3:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    //$exp3="((\s*</[^>]+>\s*)*)";
    $exp3="(([^<>]*</[^>]+>[^<>]*)*)";
    et ce serait fait.

  5. #5
    Invité
    Invité(e)
    Par défaut
    Ce script semble donner le résultat escompté :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    	$PointSuspension 	= '...';
    	$texte		.= 'ReplacePointSuspension'; // (au cas où d'autres "..." seraient dans le texte)
    	$pattern	= '#(<[^>]*/[^>]*>[\n\t\r ]*)(ReplacePointSuspension)#i';
    		while (preg_match($pattern, $texte)){
    			$texte	= preg_replace($pattern, '${2}${1}', $texte);
    		}
    		$texte2	= str_replace('ReplacePointSuspension', '...', $texte);
    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <root>
        <x>AAAA
            <y attr="y">
                <z>BB...BB
                    <p>
                        <q a="q"></q>
                    </p>dernier texte : ICI
                </z>
                <img src="xxx" alt="..." />
            </y>
            <br />
        </x>
    </root>
    => les points de suspension se placent bien après le dernier texte :
    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <root>
        <x>AAAA
            <y attr="y">
                <z>BB...BB
                    <p>
                        <q a="q"></q>
                    </p>dernier texte : ICI
                ...</z>
                <img src="xxx" alt="..." />
            </y>
            <br />
        </x>
    </root>
    N.B. Les balises auto-fermantes sont aussi "ignorés".
    Dernière modification par Invité ; 02/10/2013 à 18h13.

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo