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 :

assertions négatives


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Avril 2005
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 16
    Par défaut assertions négatives
    Bonjour à tous,

    Je vous expose ici un problème d'expression régulière en apparence assez simple mais sur lequel je bloque depuis quelques temps : regex builders, assistants, rien n'y fait, pas moyen...

    Le problème :
    Je dois analyser un fichier texte complet et remplacer toutes les occurences d'un mot donné (ex: toto) par une certaine valeur (ex: titi), mais uniquement si ce mot n'est pas compris entre crochets ou accolades, directement ou indirectement (c'est-à-dire que dans l'exemple [un_mot toto tutu], toto ne doit pas être inclus).

    Les solutions envisagées
    J'ai lu quelques articles notamment sur les assertions négatives, pensant qu'une expression du genre (?<!\[)+(.*)toto(.*)+(?!\]) ferait l'affaire, en essayant plusieurs variantes, mais rien n'y a fait, même si leur usage m'a permis de m'approcher du résultat.

    Votre aide serait donc grandement appréciée, aussi je vous en remercie d'avance

  2. #2
    Membre Expert Avatar de Madfrix
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    2 326
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 326
    Par défaut
    Bonjour,

    y'a forcément moyen avec les regex, mais sinon tu peux faire une fonction maison

    Code php : 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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
     
    $chaine = 'dfsd toto[fgdfg toto dfds]dfg [d toto toto][toto';
     
    function killToto($chaine, $replaceBy){
     
    	$sortie = '';
    	$isKillPossible = false;		
     
    	$countChaine = strlen($chaine);
    	$i=0;
     
    	while(true){
    		if($i > $countChaine)
    			break;
     
    		$c = substr($chaine, $i, 1);
     
    		if($c == '['){
    			$isKillPossible = true;
    			$sortie .= $c;
    		}elseif($c == ']'){
    			$isKillPossible = false;
    			$sortie .= $c;
    		}elseif(strtolower($c) == 't' && $isKillPossible == true && strtolower(substr($chaine, $i, 4)) == 'toto' && verifNext($chaine, $i)){
    			$sortie .= $replaceBy;
    			$i += 4;
    			continue;
    		}else{
    			$sortie .= $c;
    		}
     
    		$i++;
     
    	}
     
    	return $sortie;
     
    }
     
    function verifNext($chaine, $i){
     
    	$countChaine = strlen($chaine);
     
    	while(true){
     
    		if($i > $countChaine)
    			return false;
     
    		if(substr($chaine, $i, 1) == ']')
    			return true;
     
    		$i++;
    	}
     
    }
     
    echo killToto($chaine, 'ok');
     
    //Affiche
    dfsd toto[fgdfg ok dfds]dfg [d ok ok][toto

  3. #3
    Rédacteur/Modérateur

    Avatar de SpaceFrog
    Homme Profil pro
    Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Bidouilleur SharePoint
    Inscrit en
    Mars 2002
    Messages
    39 659
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Bidouilleur SharePoint
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2002
    Messages : 39 659
    Billets dans le blog
    1
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    $reg="~(?:<)(?>titi)(?>>)~";
    $chaine="<titi>titititi<titi>titititititi<titi>titititititi";
    $res=preg_replace($reg,'<b style="color:red">TOTO</b>',$chaine);
    ?>		
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    </head>
    <body>
    <?php
    echo $res;
    	?>
    </body>
    </html>
    Ma page Developpez - Mon Blog Developpez
    Président du CCMPTP (Comité Contre le Mot "Problème" dans les Titres de Posts)
    Deux règles du succès: 1) Ne communiquez jamais à quelqu'un tout votre savoir...
    Votre post est résolu ? Alors n'oubliez pas le Tag

    Venez sur le Chat de Développez !

  4. #4
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    SpaceFrog, peux tu expliquer ta RE ~(?:<)(?>titi)(?>>)~ stp.

    Je ne la comprends pas et en l’essayant sous Python, j’obtiens le message d’erreur:
    error: unexpected end of pattern







    Madfrix, ton code est impressionant mais étant donné que « y'a forcément moyen avec les regex » , il vaut mieux à mon avis chercher une vraie solution avec regex.







    Pour ma part , j’ai rapidement trouvé une solution hier soir en Python, mais elle n’est valable que pour une modif tenant compte seulement des crochets.

    Le principe en est de splitter la chaîne selon les segments ’[.........]’ : on obtient ainsi deux types de segments, qui alternent dans une liste.

    Il suffit alors de ne faire le remplacement des 'totoi' que dans les segments autres que les ’[..............]’ , ce qui est facile puisqu’en parcourant la liste de la chaîne splittée, les segments ’[.................]’ sont tous avec des index impairs dans la liste (premier élément de la liste a index 0 ) et donc n’ont pas leurs totoi substitués tandis que les autres sont d’index pairs et ont leur 'totoi' remplacés.



    Ensuite on recolle l’ensemble des segments.

    Dans ce code, il y a deux regex:
    une pour détecter les segments ’[....................]’ : (\[[^[\]]*\])

    et l’autre pour détecter les mots ’totoi’ : (\W|\A)(toto\d)(\W|\Z)

    les \W de part et d’autre signifient que ne sont considérés comme mots 'toto0', 'toto1', 'toto2' etc que les 'totoi' qui ne font pas partie d’un mot plus long
    Les \A et \Z sont là parce que le mot 'totoi' peut être au début ou à la fin du segment résultant de la découpe par split().

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    ch = '''ab toto0 cd fg[h kj toto1 mnh ] uk toto2 [ju toto3] pa toto4[toto5 vfr]
    fd toto6 qw [toto7 nhft [jkiu toto8 k]toto9 nb [ard toto0 pototo1 f[ru toto2 n]'''
    
    import re
    
    pat = re.compile('(\[[^[\]]*\])')
    pat_totod = re.compile('(\W|\A)(toto\d)(\W|\Z)')
    
    print ch,'\n'
    print pat.split(ch),'\n'
    print ''.join( pat_totod.sub('\\1EDGAR\\3',u) if i%2==0 else u
                   for i,u in enumerate( pat.split(ch) ) )



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    ab toto0 cd fg[h kj toto1 mnh ] uk toto2 [ju toto3] pa toto4[toto5 vfr]
    fd toto6 qw [toto7 nhft [jkiu toto8 k]toto9 nb [ard toto0 pototo1 f[ru toto2 n] 
    
    ['ab toto0 cd fg', '[h kj toto1 mnh ]', ' uk toto2 ', '[ju toto3]', ' pa toto4', '[toto5 vfr]', '\nfd toto6 qw [toto7 nhft ', '[jkiu toto8 k]', 'toto9 nb [ard toto0 pototo1 f', '[ru toto2 n]', ''] 
    
    ab EDGAR cd fg[h kj toto1 mnh ] uk EDGAR [ju toto3] pa EDGAR[toto5 vfr]
    fd EDGAR qw [EDGAR nhft [jkiu toto8 k]EDGAR nb [ard EDGAR pototo1 f[ru toto2 n]

    Le problème de ce code, c’est que ça ne traite que par rapport aux crochets et que rajouter la prise en compte des accolades, ça corse le problème et jusqu’à présent j’ai calé.
    J’ai une vague idée ce matin, il faut que je vois ça.





    Il faut aussi remarquer que les résultats dépendent de la façon dont on définit la RE pour capturer les segments ’[...................]’.

    J’ai fait en sorte qu’entre les deux crochets extrèmes d’un segment ’[........................]’ , il n’y ait pas de signe ’]’ ni de ’[’. On pourrait en décider autrement. Mais comme ce n’est pas précisé dans la question, j’ai fait un choix.

    Est-ce qu’on pourrait avoir une directive sur ce point stp SSJ17Vegeta.




    PS

    J’aurais bien essayé de coder en PHP mais j’ai retéléchargé et réinstallé WAMP5 et je n’arrive plus à exécuter des codes comme avant.

    J’ai un fichier C:\wamp\www\fichier.php dans www directory, mais quand je vais dans http://localhost/ je ne le vois pas. Il me semble que c’était bien ainsi que je faisais avant: aller dans http://localhost/. Est-ce correct ?

    D’autre part, les fichiers doivent-ils bien avoir l’extension .php ?

  5. #5
    Rédacteur/Modérateur

    Avatar de SpaceFrog
    Homme Profil pro
    Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Bidouilleur SharePoint
    Inscrit en
    Mars 2002
    Messages
    39 659
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Bidouilleur SharePoint
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2002
    Messages : 39 659
    Billets dans le blog
    1
    Par défaut
    je pense qu'en python il faut echapper les < ou >

    en fait la reg devrait être

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $reg="~(?:<)(?>titi)(?>(?:>))~";
    (?:<) => groupe non capturant < ouvrant
    (?>titi) suivi de titi
    (?>(?:>)) suivi d'un groupe non capturant > fermant
    Ma page Developpez - Mon Blog Developpez
    Président du CCMPTP (Comité Contre le Mot "Problème" dans les Titres de Posts)
    Deux règles du succès: 1) Ne communiquez jamais à quelqu'un tout votre savoir...
    Votre post est résolu ? Alors n'oubliez pas le Tag

    Venez sur le Chat de Développez !

  6. #6
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    En python les assertions s’écrivent:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ?=     assertion positive en avant
    ?!     assertion négative en avant
     
    ?<=     assertion positive en arrière
    ?<!     assertion négative en arrière


    Ta RE se traduit par " (?:\[)(?=titi)(?=(?:\])) " en Python si je comprends bien.

    J’ai mis des [ et ] à la place des < et > puisque SSJ17Vegeta parle de crochets et accolades.

    Je ne comprends pas ta logique.
    Le mot titi n’est pas censé se trouver juste après un crochet ouvrant comme l'exprime (?:\[)(?=titi)

    En plus s’il n’y a que des (?: ) et (?= ) , je ne vois pas ce qui est capturé.

    En outre, en Python une assertion ne définit pas un groupe capturant. Est-ce différent en PHP ?




    Est-ce que tu as fait tourner ton code, SpaceFrog ?
    Quel résultat obtiens tu sur avec les chaînes suivantes ?


    '''ab toto0 cd fg[h kj toto1 mnh ] uk toto2 [ju toto3] pa toto4[toto5 vfr]
    fd toto6 qw [toto7 nhft [jkiu toto8 k]toto9 nb [ard toto0 pototo1 f[ru toto2 n]'''




    '''ab toto0 cd fg[h kj toto1 mnh ] uk toto2 gt{jh toto3 bg} ff
    de { bbfe toto4++ {ngt toto5} vu [gtre { gt toto6 y]mju} hh
    fd {ggdug toto7 fdg[ {kju toto8 sd[ gtre ==toto9 {[toto0 ku} gf
    {{{ gtr [lkj toto1 bg]]]]] { gt toto2}}[{}} gtr toto3]}
    [ju toto3] pa{j toto4[ toto5 v}fr{]{ kiu ]{kju toto6 toto7 {} toto8]
    fd toto6 qw [toto7 nhft [jkiu toto8 k]toto9 nb [ard toto0 pototo1 f[ru toto2 n]'''

Discussions similaires

  1. [Python 2.X] probleme expression reguliere assertion avant négative
    Par xavier-Pierre dans le forum Général Python
    Réponses: 2
    Dernier message: 03/04/2015, 12h54
  2. [RegEx] Assertions négatives
    Par nasuu dans le forum Langage
    Réponses: 2
    Dernier message: 17/05/2010, 10h40
  3. [RegEx] Assertion avant négative
    Par orus8 dans le forum Langage
    Réponses: 2
    Dernier message: 06/03/2009, 09h34
  4. [RegEx] Assertion négative avec ereg_replace()
    Par citronbleu-v dans le forum Langage
    Réponses: 2
    Dernier message: 17/04/2008, 14h11
  5. [RegEx] Assertion négative dans une classe
    Par xuoy dans le forum Langage
    Réponses: 8
    Dernier message: 20/02/2006, 11h59

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