Précédent   Forum des professionnels en informatique > PHP > Langage > Regex
Regex Forum d'entraide sur les expressions rationnelles PHP. Avant de poster -> FAQ regex, Cours de regex et Sources de regex
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
Vieux 12/05/2006, 18h09   #1
Membre habitué
 
Avatar de php_de_travers
 
Inscription : juin 2004
Messages : 460
Détails du profil
Informations forums :
Inscription : juin 2004
Messages : 460
Points : 144
Points : 144
Par défaut Lien automatique

Bonjour,

j'utilise la manip suivante pour modifier mes textes

Code :
1
2
3
4
5
6
7
8
9
10
function affiche_texte_auto_lien ($texte)
                    {
                        $texte =  stripslashes ($texte ) ;  
 
                        $texte = ereg_replace ("arbitre", "<strong><a href=\"../arbitres/arbitre.php\">arbitre</a></strong>" , $texte) ; 
 
                        print (nl2br($texte)) ;
                        return ($texte) ;
 
                    }
Mon problème est que si je fais pareil pour le mot foot, il génère un lien à l'intérieur même du mot football, ce qui le rend difficilement lisible.
En revanche, avec foot. et foot, rien ne se passe à cause des signes de ponctuation qui suivent.

Est-il possible de lui faire reconnaître les mots complets, et non pas les morceaux de mots et de permettre une reconnaissance même si le mot est suivi d'une virgule, d'un point etc... ?
Par avance, merci de votre aide.
php_de_travers est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/05/2006, 18h15   #2
Membre chevronné
 
Avatar de stunti
 
Inscription : mai 2006
Messages : 521
Détails du profil
Informations personnelles :
Âge : 33

Informations forums :
Inscription : mai 2006
Messages : 521
Points : 602
Points : 602
utilise plutot un preg_replace

voila la regexp (vite fait)

Code :
[^0-9,a-z]arbitre[^0-9,a-z]
stunti est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/05/2006, 18h29   #3
Membre habitué
 
Avatar de php_de_travers
 
Inscription : juin 2004
Messages : 460
Détails du profil
Informations forums :
Inscription : juin 2004
Messages : 460
Points : 144
Points : 144
Merci bien pour cette piste.
Si ce n'est pas trop abuser, ça donne quoi sur un cas concret comme :

Code :
$texte = ereg_replace ("arbitre", "<strong><a href=\"../arbitres/arbitre.php\">arbitre</a></strong>" , $texte) ;
php_de_travers est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/05/2006, 18h32   #4
Membre chevronné
 
Avatar de stunti
 
Inscription : mai 2006
Messages : 521
Détails du profil
Informations personnelles :
Âge : 33

Informations forums :
Inscription : mai 2006
Messages : 521
Points : 602
Points : 602
le mieux :
PCRE est plus rapide que POSIX
tu vas sur l'onglet PCRE (preg_*) ou POSIX (ereg*) et tu t'amuses :

REX V
stunti est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/05/2006, 18h37   #5
Membre habitué
 
Avatar de php_de_travers
 
Inscription : juin 2004
Messages : 460
Détails du profil
Informations forums :
Inscription : juin 2004
Messages : 460
Points : 144
Points : 144
Voilà une réponse qui ouvre encore de nouveaux horizons.
Merci vraiment beaucoup !

Rectification : j'ai rien comprendu à cette usine à gaz.
Si quelqu'un a la solution à mon pb,... !

Dernière modification par php_de_travers ; 12/05/2006 à 18h50.
php_de_travers est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/05/2006, 19h09   #6
Membre habitué
 
Avatar de php_de_travers
 
Inscription : juin 2004
Messages : 460
Détails du profil
Informations forums :
Inscription : juin 2004
Messages : 460
Points : 144
Points : 144
Par hasard, je viens de trouver ça :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php 
$ch='Bon alors voilou, la bonne méthode consiste à limiter les 
 mots de façon à éviter de prendre une partie, comme sol dans 
 solide, bravo dans bravoure et bon dans bonne comme au début, 
 même si BRAVO ou BON sont en majuscules ou encore un mix des 
 deux et au pluriel comme BrAVoS.'; 
 
$mot=array('bravo','bon','sol'); 
 
$motif='`\b(('.implode('|',$mot).')s?)\b`si'; 
 
$sortie='<span style="background-color:#ffcc00">$1</span>'; 
echo preg_replace($motif,$sortie,$ch); 
?>
C'était sur http://www.expreg.com
php_de_travers est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/05/2006, 20h03   #7
Expert Confirmé Sénior
 
Avatar de Mr N.
 
Inscription : septembre 2004
Messages : 5 421
Détails du profil
Informations forums :
Inscription : septembre 2004
Messages : 5 421
Points : 5 836
Points : 5 836
Code :
$texte = preg_replace ('/\barbitre\b/', "<strong><a href=\"../arbitres/arbitre.php\">arbitre</a></strong>" , $texte) ;
Mr N. est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/05/2006, 22h17   #8
Membre habitué
 
Avatar de php_de_travers
 
Inscription : juin 2004
Messages : 460
Détails du profil
Informations forums :
Inscription : juin 2004
Messages : 460
Points : 144
Points : 144
Merci pour ta réponse précise à ma question.

Une recherche approfonfie sur le web et pas mal d'expérimentation empirique me permettent de proposer ce qui suit.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
$paragraphe ='Dans les années 70, l'équipe de football de Saint-Etienne a fait rêver des milliers de supporters. Sait-on si notre Zizou national n'est pas la concrétisation de ce rêve.';
 
function affiche_texte_auto_lien ($texte)
    {
        $texte = preg_replace('`\b(('.football.')s?)\b`si','<strong><a href="../football.php">$1</a></strong>',$texte);
        $texte = preg_replace('`\b(('.zizou.')s?)\b`si','<strong><a href="../zinedine-zidane.php">$1</a></strong>',$texte);
        $texte = preg_replace('`\b(('.millier.')s?)\b`si','<strong><a href="../nombres.php">$1</a></strong>',$texte);
 
        print (nl2br($texte)) ;
    }
 
$paragraphe = affiche_texte_auto_lien ($paragraphe) ;
?>
Ca fait exactement ce que je cherchais et même mieux encore !
Le hic, ce sont les mots composés : Saint Etienne est refusé.
php_de_travers est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/05/2006, 22h27   #9
Rédacteur
 
Avatar de Yogui
 
Homme Guillaume Rossolini
Directeur technique
Inscription : février 2004
Messages : 13 700
Détails du profil
Informations personnelles :
Nom : Homme Guillaume Rossolini
Localisation : France

Informations professionnelles :
Activité : Directeur technique

Informations forums :
Inscription : février 2004
Messages : 13 700
Points : 17 202
Points : 17 202
Salut

Il y a de sérieux problèmes à ta regex :/
Tu concatènes la constante football à la regex mais, puisqu'elle n'existe pas, PHP la convertit en chaîne littérale donc ça marche. Mais ça devrait pas. Normalement, tu devrais avoir un joli Warning à ce sujet : j'imagine que tu as enlevé l'error_reporting dans ton php.ini.

Solution : remplacer
par
Ensuite, tu utilises beaucoup de parenthèses inutiles. Puisque tu sais que tu vas avoir "football", tu n'as pas besoin d'utiliser les parenthèses et $1.
__________________
Mes articles - Zend Certified Engineer (PHP + Zend Framework)
Ressources PHP - Ressources Zend Framework
Yogui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/05/2006, 22h31   #10
Membre habitué
 
Avatar de php_de_travers
 
Inscription : juin 2004
Messages : 460
Détails du profil
Informations forums :
Inscription : juin 2004
Messages : 460
Points : 144
Points : 144
La proposition de Mr. N est excellent pour les mots composés :

Code :
$texte = preg_replace ('/\bSaint Etienne\b/', "<strong><a href=\"../les-verts.php\">Saint Etienne</a></strong>" , $texte) ;
Est-ce que quelqu'un comprend le coup du s? et si dans le pattern
'`\b(('.millier.')s?)\b`si'

Ca sert à reconnaître la version au pluriel d'un mot proposé initialement au singulier.
Mais je ne sais pas du tout comment ça fonctionne...

PS : comment faites-vous pour maîtriser des trucs pareils, les modérateurs et autre participants à ce forums ?
php_de_travers est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/05/2006, 23h03   #11
Rédacteur
 
Avatar de Yogui
 
Homme Guillaume Rossolini
Directeur technique
Inscription : février 2004
Messages : 13 700
Détails du profil
Informations personnelles :
Nom : Homme Guillaume Rossolini
Localisation : France

Informations professionnelles :
Activité : Directeur technique

Informations forums :
Inscription : février 2004
Messages : 13 700
Points : 17 202
Points : 17 202
Le s permet de dire à ton point (dans l'expression) qu'il doit aussi remplacer les sauts de line ("\n" et compagnie). Donc si tu n'as pas de point dans ta regex, tu n'as pas besoin du modificateur s.
Le i permet d'ignorer la casse (majuscules == minuscules).
Le point d'interrogation ? permet de matcher, que le caractère soit là ou non. On peut l'appliquer comme l'étoile * (zéro jusqu'à l'infini) et le plus + (au moins un).
Lis bien la doc PHP sur les regex, tout y est expliqué.

C'est à force...
__________________
Mes articles - Zend Certified Engineer (PHP + Zend Framework)
Ressources PHP - Ressources Zend Framework
Yogui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/05/2006, 08h03   #12
Expert Confirmé Sénior
 
Avatar de Mr N.
 
Inscription : septembre 2004
Messages : 5 421
Détails du profil
Informations forums :
Inscription : septembre 2004
Messages : 5 421
Points : 5 836
Points : 5 836
Je dis que le s c'est pour un millier, des milliers
Mr N. est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/05/2006, 11h01   #13
Membre habitué
 
Avatar de php_de_travers
 
Inscription : juin 2004
Messages : 460
Détails du profil
Informations forums :
Inscription : juin 2004
Messages : 460
Points : 144
Points : 144
De plus en plus tordu !

J'ai plusieurs mots qui génèrent ce genre de mis en valeur automatique :
- zizou
- Platini
- joueurs
- etc...

Code :
1
2
3
4
5
6
7
8
9
<?php
$texte = "Quelques joueurs français connus internationalement : Michel Platini, Zinédine Zidane, dit Zizou" ; 
 
        $texte = preg_replace('`\b(('.zizou.')s?)\b`si','<strong><a href="../joueur/index.php">$1</a></strong>',$texte);
        $texte = preg_replace('`\b(('.platini.')s?)\b`si','<strong><a href="../joueur/joueur.php">$1</a></strong>',$texte);
        $texte = preg_replace('`\b(('.joueur.')s?)\b`si','<strong><a href="../joueur/index.php">$1</a></strong>',$texte);
 
print $texte ; 
?>
Miracle : le seul fait que le mot joueur soit à la fois un répertoire et un mot qui se met lui-même en lien par la fonction génère un cafouillage énorme.

Résultat qui se mord la queue :
Citation:
Quelques joueurs français connus internationalement : Michel joueur/joueur.php">Platini, Zinédine Zidane, dit joueur/index.php">Zizou
Si vous savez comment éviter que la méthode boucle sur elle même...
php_de_travers est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/05/2006, 12h02   #14
Rédacteur
 
Avatar de Yogui
 
Homme Guillaume Rossolini
Directeur technique
Inscription : février 2004
Messages : 13 700
Détails du profil
Informations personnelles :
Nom : Homme Guillaume Rossolini
Localisation : France

Informations professionnelles :
Activité : Directeur technique

Informations forums :
Inscription : février 2004
Messages : 13 700
Points : 17 202
Points : 17 202
Hmmm, comment dire...
Cela ne t'a pas mis la puce à l'oreille ?
Un langage de script (comme PHP) n'est pas prévu pour effectuer des tâches trop spécifiques. Si tu répètes une tâche spécifique en changeant peu de choses (c'est le cas pour cette regex), alors peut-être qu'il serait plus intéressant de revoir la structure de ton site.
En l'occurence, je trouve assez peu judicieux d'avoir une page "zidane.php" : j'aurais essayé de me situer au niveau de la classe plutôt que de l'objet, pour parler en termes de prog orientée objet.

Exemple : "Zidane" est un joueur de foot. Il n'est probablement pas exclu que tu ajoutes d'autres joueurs par la suite, donc pourquoi ne pas nommer ton script "joueurs.php" et lui donner un paramètre "nom=Zidane" ? Ou bien tu places le tout dans un répertoire joueurs/ et le script d'appelle index.php.
Finalement, ta regex aura quelque chose comme ceci à remplacer :
Citation:
joueurs.php?nom=zidane
joueurs.php?nom=platini
joueurs.php
equipes.php?nom=Saint%20Etienne
__________________
Mes articles - Zend Certified Engineer (PHP + Zend Framework)
Ressources PHP - Ressources Zend Framework
Yogui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/05/2006, 21h16   #15
Membre habitué
 
Avatar de php_de_travers
 
Inscription : juin 2004
Messages : 460
Détails du profil
Informations forums :
Inscription : juin 2004
Messages : 460
Points : 144
Points : 144
J'ai enfin trouvé une solution :

Code :
1
2
3
4
5
6
7
$texte = "Quelques joueurs français connus internationalement : Michel Platini, Zinédine Zidane, dit Zizou." ; 
 
        $texte = preg_replace('`\b(('.joueur.')s?)\b`si','<strong><a href="../joueur/index.php">$1</a></strong>',$texte);
        $texte = preg_replace('`\b(('.zizou.')s?)\b`si','<strong><a href="../joueur.php">$1</a></strong>',$texte);
        $texte = preg_replace('`\b(('.platini.')s?)\b`si','<strong><a href="../joueur/joueur.php">$1</a></strong>',$texte);
 
print $texte ;
C'est à dire, commencer par les mots qui sont à la fois mots-clés + noms de répertoires et/ou de fichiers.

Je ne sais pas pourquoi, mais ça marche.
NB : ça marche pour les mots isolés, pas les groupes de mots ("Marius Trésor").

Dernière modification par php_de_travers ; 14/05/2006 à 22h03.
php_de_travers est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/05/2006, 22h13   #16
Membre habitué
 
Avatar de php_de_travers
 
Inscription : juin 2004
Messages : 460
Détails du profil
Informations forums :
Inscription : juin 2004
Messages : 460
Points : 144
Points : 144
Citation:
Envoyé par Yogui
Salut

Il y a de sérieux problèmes à ta regex :/
Tu concatènes la constante football à la regex mais, puisqu'elle n'existe pas, PHP la convertit en chaîne littérale donc ça marche. Mais ça devrait pas. Normalement, tu devrais avoir un joli Warning à ce sujet : j'imagine que tu as enlevé l'error_reporting dans ton php.ini.

Solution : remplacer
par
Ensuite, tu utilises beaucoup de parenthèses inutiles. Puisque tu sais que tu vas avoir "football", tu n'as pas besoin d'utiliser les parenthèses et $1.
Merci pour cette correction :

la nouvelle version de la procédure est :

$texte = preg_replace('`\b((joueur)s?)\b`si','<strong><a href="../joueur/index.php">$1</a></strong>',$texte);

Et elle fonctionne très bien.
php_de_travers est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +1. Il est actuellement 06h37.


 
 
 
 
Partenaires

Hébergement Web