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 19/05/2007, 00h10   #1
Invité de passage
 
Inscription : août 2006
Messages : 8
Détails du profil
Informations forums :
Inscription : août 2006
Messages : 8
Points : 1
Points : 1
Par défaut Regex avec condition

Bonsoir !

Je suis sur une regex qui me casse la cabeza... Je suis pas un pro des expressions régulières, mais j'arrive toujours à m'en sortir et finalement à trouver.

Hors, celà fait 2 jours que je pense qu'à celle là, et là ca devient trop obsessionnelle, donc j'ai besoin d'aide ^^.

Voici un panel d'exemple de string cible :

<a href="http://www.lebon.com/test/de/accueil/index.html>
<a href="http://www.lebon.com/fr/accueil/index.html>
<a href="http://www.lebon.com/accueil/index.html>
<a href="test/it/accueil/index.html>
<a href="jessaye/nimportequoi/test/pt/accueil/patati/patata/kaisoif.html>
<a href="images/accueil/index.html>
<a href="http://www.lemauvais.com/test/de/accueil/index.html>

J'aimerais donc modifier le mot accueil en home. Mais j'ai plusieurs conditions :

- si http dans le href alors que http://www.lebon.com
- accueil est forcément précéde de : /(de?|es?|it?|nl?|pt?|gb?|fr?)/
- si il y a un mot dans le href commencant par imag* je ne prends pas en compte.

Dans mes exemples les n° 1, 2, et 4 sont bons pas les autres.

J'ai commencé par essayer de faire un match et de voir ensuite comment prendre qu'une partie :

<a href="(http://www.lebon.com/?)(.*)/(:?fr?|gb?|de?|es?|it?|nl?|pt?)/accueil/

Mais çà m'a embrouillé plus qu'autre chose et je tourne en rond :s

Si un regex guru passe par là et a du temps ca me ferait bien plaisir ^^


Merci beaucoup !

Yudao.
yudao est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/05/2007, 12h08   #2
Membre chevronné
 
Avatar de Korko Fain
 
Étudiant
Inscription : août 2005
Messages : 632
Détails du profil
Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : août 2005
Messages : 632
Points : 632
Points : 632
Visiblement tu n'as pas donné toutes les conditions car la 5 répond à tes conditions mais tu dis qu'elle est fausse

Sinon je pense que ça fera l'affaire même si ça consomme 3 regex.
Code php :
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
function preg_match_all_callback($regex, $callback, $string, &$result)
{
	preg_match_all($regex, $string, $matches);
 
	foreach($matches as $match)
	{
		if (call_user_func($callback, $match))
		{
			$result[] = $match;
		}
	}
}
 
function test_string($match)
{
	// Si on trouve http:// non suivi de www.lebon.com
	// Si on trouve acceuil non précédé de /de/ ou /es/ ou /it/ ou /nl/ ou /pt/ ou /gb/ ou /fr/
	// Si on trouve un mot (\b) qui commence par imag
	// On retourne FALSE (faux)
	if( preg_match('#http://(?!www.lebon.com/)#', $match[1]) || preg_match('#(?<!/(de|es|it|nl|pt|gb|fr)/)acceuil#', $match[1]) || preg_match('#\bimag#', $match[1]) )
	{
		return FALSE;
	}
 
	return TRUE;
}
 
preg_match_all_callback('#<a href="(.*)"#Ui', 'test_string', $chaine, $matches);
Korko Fain est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/05/2007, 01h03   #3
Membre habitué
 
Avatar de daniel61
 
Inscription : décembre 2006
Messages : 109
Détails du profil
Informations forums :
Inscription : décembre 2006
Messages : 109
Points : 120
Points : 120
Citation:
Envoyé par yudao
Je suis sur une regex qui me casse la cabeza... Je suis pas un pro des expressions régulières, mais j'arrive toujours à m'en sortir et finalement à trouver.
il n'y a pas de mal à découper un problème comme te le propose Korko Fain. mon choix personnel irait vers preg_replace_callback() puisque c'est un cas de remplacement.

Citation:
Envoyé par yudao
Hors, celà fait 2 jours que je pense qu'à celle là, et là ca devient trop obsessionnelle
oui, ça peut se faire en 1 regex. je vais te proposer quelque chose pas nécessairement agréable pour les neurones par contre.

Citation:
Envoyé par yudao
<a href="jessaye/nimportequoi/test/pt/accueil/patati/patata/kaisoif.html">
je vais supposer que accueil n'est pas remplacé parcequ'il n'est pas le dernier répertoire.

Citation:
Envoyé par yudao
<a href="
href précédé d'un espace me semble suffisant et il faut considérer la possibilité d'espaces autour de = le caractère ' peut aussi être utilisé pour délimiter le lien.

\shref\s*=\s*([\'"]) en capturant le caractère ' ou " la regex pourra utiliser cette capture pour reconnaitre la fin du lien.

Citation:
Envoyé par yudao
(http://www.lebon.com/?)
la torture des neurones commence ici... il existe les assertions dans pcre, une assertion est simplement une validation qui ne capture pas, qui ne déplacement pas le curseur sur la chaine source, mais qui fait un test sur les caractères suivants ou précédants le curseur. il y a plusieurs types d'assertions, et pour ce premier éléments il faudra 2 assertions, une conditionnelle et si elle est vrai alors une avant positive complètera le travail.

(?(condition)pattern__si_vrai|pattern_si_faux) est la forme d'une conditionnelle. la condition doit obligatiorement être une assertion, le "pattern_si_faux" est optionnel...

(?=caractères) est la forme d'une avant positive, l'assertion teste si les caractères suivants le curseur sont identiques... sans déplacer le curseur.

(?(?=http://)(?=http://www.lebon.com)) revient à dire que si les caractères suivants " ou ' sont http:// alors poursuivre si et seulement si les caractères suivant " ou ' sont http://www.lebon.com et il n'y a aucun besoin d'un "pattern_si_faux". les assertions ne déplacent pas le curseur, mais comme il n'y a pas de condition en conflit, pas besoin de forcer le déplacement.

Citation:
Envoyé par yudao
(.*)
j'imagine que tu voulais garder la négation de imag* pour la fin... un mot commencant par imag peut s'écrire avec imag précédé par \b qui est une classe de caractère particulère puisqu'une assertion... \b représente tous les caractère non alphanumérique en excluant aussi le caractère _ qui est membre de la classe \w. la forme de la négation d'une séquence de caractère est (?!caractères) mais c'est aussi une assertion, donc ça ne déplace pas le curseur sur la chaine source... il faudra utiliser le méta-caractère . avec un sous-masque pour forcer le déplacement.

(?:(?!\bimag).)+? permet de parcourir en ungreedy le contenu de href et d'arrêter si un mot débutant par imag est rencontré.

Citation:
Envoyé par yudao
/(:?fr?|gb?|de?|es?|it?|nl?|pt?)
pt? a pour effet de permettre 0 ou 1 fois le t seulement. la répétition évidente est {1} puisqu'il faut toujours une fois un et un seul des éléments de l'énumération.
/(?:de|es|it|nl|pt|gb|fr){1}

maintenant, il est temps de faire la capture en \\1 de ce qui précéde /accueil/ pour pouvoir faire une remplacement \\1/home/...

Code :
1
2
(\shref\s*=\s*([\'"])(?(?=http://)(?=http://www.lebon.com))(?:(?!\bimag).)+?/(?:de|es|it|nl|pt|gb|fr){1})/accueil/
si jamais il doit y avoir remplacement de /accueil/ dans <a href="jessaye/nimportequoi/test/pt/accueil/patati/patata/kaisoif.html"> alors la regex est complète et tu pourras aussi enlever la capture sur ([\'"]) parceque non nécessaire.

par contre, s'il faut faire le remplacement de /accueil/ seulement si c'est le dernier répertoire, alors il faudra faire une capture en \\3 de la suite si valide bien entendu.

([^/]+?\2) revient à nier le caractère / jusqu'au caractère qui aura été capturé en \\2... le fameux ([\'"]), donc si c'était " alors \2 contiendra ", et si c'était ' alors \2 contiendra '. si un caractère / est rencontré, alors le regex se terminera et aucun remplacement ne sera fait... le tout capturé en \\3 puisque \\2 contient le caractère délimitant le lien.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
 
$html='
<a href="http://www.lebon.com/test/de/accueil/index.html">
<a href="http://www.lebon.com/fr/accueil/index.html">
<a href="http://www.lebon.com/accueil/index.html">
<a href="test/it/accueil/index.html">
<a href="jessaye/nimportequoi/test/pt/accueil/patati/patata/kaisoif.html">
<a href="images/accueil/index.html">
<a href="http://www.lemauvais.com/test/de/accueil/index.html">
';
 
$resultat=preg_replace('#(\shref\s*=\s*([\'"])(?(?=http://)(?=http://www.lebon.com))(?:(?!\bimag).)+?/(?:de|es|it|nl|pt|gb|fr){1})/accueil/([^/]+?\2)#is','\\1/home/\\3',$html);
echo htmlentities($resultat);
daniel61 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/05/2007, 10h07   #4
Membre chevronné
 
Avatar de Korko Fain
 
Étudiant
Inscription : août 2005
Messages : 632
Détails du profil
Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : août 2005
Messages : 632
Points : 632
Points : 632
Ce n'est pas \\2 plutot que \2 ?
Sinon, tres tres bon descriptif. A garder sous le coude ^^
Korko Fain est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/05/2007, 04h50   #5
Membre habitué
 
Avatar de daniel61
 
Inscription : décembre 2006
Messages : 109
Détails du profil
Informations forums :
Inscription : décembre 2006
Messages : 109
Points : 120
Points : 120
Citation:
Envoyé par Korko Fain
Ce n'est pas \\2 plutot que \2 ?
des équivalences. je préfère \2 dans l'expression et \\2 dans la chaîne de remplacement.
daniel61 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/05/2007, 11h24   #6
Membre chevronné
 
Avatar de Korko Fain
 
Étudiant
Inscription : août 2005
Messages : 632
Détails du profil
Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : août 2005
Messages : 632
Points : 632
Points : 632
Ok je connaissai les équivalences \\2 et $2 mais pas \2 ^^

De plus, le {1} n'est pas nécéssaire puisqu'il est compté par défaut...
Korko Fain est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/05/2007, 15h08   #7
Membre habitué
 
Avatar de daniel61
 
Inscription : décembre 2006
Messages : 109
Détails du profil
Informations forums :
Inscription : décembre 2006
Messages : 109
Points : 120
Points : 120
Citation:
Envoyé par Korko Fain
De plus, le {1} n'est pas nécéssaire puisqu'il est compté par défaut...
exact
daniel61 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 +2. Il est actuellement 02h48.


 
 
 
 
Partenaires

Hébergement Web