Discussion:
Expression rationnelle
(trop ancien pour répondre)
Stéphane Santon
2013-05-11 21:56:34 UTC
Permalink
Bonjour,

Pour le calcul d'une url, je désire filtrer les petits mots de mon
choix dans une chaine :
- placés en début de chaine et suivis d'un tiret,
- placés en fin de chaine et précédés d'un tiret,
- placés dans la chaine et entourés d'un tiret.

Voici ce que je fais et qui fonctionne.

$lsMasque = array(
'(^au-|^de-|^du-|^des-|^en-|^l-|^le-|^la-|^les-)',
'(-au-|-de-|-du-|-des-|-en-|-l-|-le-|-la-|-les-)',
'(-au$|-de$|-du$|-des$|-en$|-l$|-le$|-la$|-les$)'
);
$lsUrl = preg_replace( $lsMasque, array('','-',''), $lsUrl);

Mais y aurait-il plus simple ?

Merci
--
Stéphane

Jeune Chambre Economique de Saintes *** http://www.jce-saintes.org
Agitateurs d'idées... accélérateurs de talents !

BTS Electrotechnique *** http://enselec.santonum.eu
denisb
2013-05-12 16:26:35 UTC
Permalink
Post by Stéphane Santon
Mais y aurait-il plus simple ?
$lsUrl =
trim(preg_replace("#(?:^|-)((?:a|d)u|des?|en|l(?:es?|a)?)(?:-|$)#", "-",
$lsUrl), "-");
--
@@@@@
E -00 comme on est very beaux dis !
’ `) /
|\_ ==”
Stéphane Santon
2013-05-12 16:53:23 UTC
Permalink
Bonjour,
$lsUrl = trim(preg_replace("#(?:^|-)((?:a|d)u|des?|en|l(?:es?|a)?)(?:-|$)#",
"-", $lsUrl), "-");
Gloups.... va falloir que j'approfondisse les règles pour comprendre
comment ça marche et l'intégrer...

En tout cas Merci ! :-D
--
Stéphane

Jeune Chambre Economique de Saintes *** http://www.jce-saintes.org
Agitateurs d'idées... accélérateurs de talents !

BTS Electrotechnique *** http://enselec.santonum.eu
denisb
2013-05-12 17:29:56 UTC
Permalink
Post by Stéphane Santon
comment ça marche
ne nous préoccupons pas des ?:
on a donc : (^|-)((a|d)u|des?|en|l(es?|a)?)(-|$)

(^|-) => un '-' ou bien le début
( => [suivi de]
(a|d)u => 'a' ou 'd' suivi de 'u' ('au' ou 'du')
| => [ou bien]
des? => 'de' seul ou pouvant être suivi de 's' ('de' ou 'des')
| => [ou bien]
en => 'en' ('en')
| => [ou bien]
l(es?|a)? => 'l' seul ou pouvant être suivi soit de 'e' pouvant être suivi
de 's', soit de 'a' ('l' ou 'le' ou 'les' ou 'la')
) => [suivi de]
(-|$) => un '-' ou bien la fin


toutes les occurrences de ton tableau étant donc remplacées par '-'
on trim pour supprimer les '-' de début et de fin (au cas où il
y en ait).
--
@@@@@
E -00 comme on est very beaux dis !
’ `) /
|\_ ==”
Stéphane Santon
2013-05-13 06:33:24 UTC
Permalink
Bonjour,

Merci de ces explications.

Mais la question que je me posais surtout est :
quelle partie de syntaxe permet de ne pas supprimer le 'de' de début et
le 'les' de fin dans 'dechets-recyclables' ?
Post by denisb
Post by Stéphane Santon
comment ça marche
on a donc : (^|-)((a|d)u|des?|en|l(es?|a)?)(-|$)
(^|-) => un '-' ou bien le début
( => [suivi de]
(a|d)u => 'a' ou 'd' suivi de 'u' ('au' ou 'du')
| => [ou bien]
des? => 'de' seul ou pouvant être suivi de 's' ('de' ou 'des')
| => [ou bien]
en => 'en' ('en')
| => [ou bien]
l(es?|a)? => 'l' seul ou pouvant être suivi soit de 'e' pouvant être suivi
de 's', soit de 'a' ('l' ou 'le' ou 'les' ou 'la')
) => [suivi de]
(-|$) => un '-' ou bien la fin
toutes les occurrences de ton tableau étant donc remplacées par '-'
on trim pour supprimer les '-' de début et de fin (au cas où il
y en ait).
--
Stéphane

Jeune Chambre Economique de Saintes *** http://www.jce-saintes.org
Agitateurs d'idées... accélérateurs de talents !

BTS Electrotechnique *** http://enselec.santonum.eu
Stéphane Santon
2013-05-13 06:37:43 UTC
Permalink
quelle partie de syntaxe permet de ne pas supprimer le 'de' de début et le
'les' de fin dans 'dechets-recyclables' ?
Ah si si... c'est bon j'ai compris.
S'il y a un début avant le petit mot, il /faut/ qu'il soit suivi par un
tiret (ou la fin). Donc OK. :-)
--
Stéphane

Jeune Chambre Economique de Saintes *** http://www.jce-saintes.org
Agitateurs d'idées... accélérateurs de talents !

BTS Electrotechnique *** http://enselec.santonum.eu
Olivier Miakinen
2013-05-13 08:27:42 UTC
Permalink
Bonjour,
Post by Stéphane Santon
$lsUrl =
trim(preg_replace("#(?:^|-)((?:a|d)u|des?|en|l(?:es?|a)?)(?:-|$)#", "-",
$lsUrl), "-");
Parfois on complique en voulant simplifier... Je conserve ton idée du
trim suivant un remplacement par "-" dans tous les cas, idée que je
trouve bonne. Mais il me semble que conserver la liste de petits mots
telle quelle est plus simple que de factoriser ... et tout aussi court :

$lsUrl =
trim(preg_replace("#(?:^|-)(au|de|du|des|en|l|le|la|les)(?:-|$)#", "-",
$lsUrl), "-");

Par ailleurs, je profite de ma réponse pour rappeler qu'il existe un
groupe fr.comp.lang.regexp consacré aux expressions rationnelles. Ce
n'était pas forcément le plus adapté ici puisque la réponse comprend
un changement du code PHP, mais cela pourrait servir dans d'autres
occasions.

Cordialement,
--
Olivier Miakinen
Olivier Miakinen
2013-05-13 14:15:26 UTC
Permalink
[...] Je conserve ton idée du trim suivant un remplacement par "-"
dans tous les cas, idée que je trouve bonne.
Même si cela allait sans dire, ça va toujours mieux en le disant.
Le code de denisb fait la même chose que celui de Stéphane Santon à
trois conditions : la première condition est que la chaîne de départ
ne comporte pas de "-" au début ou à la fin ; la seconde condition
est que la chaîne de départ ne soit pas réduite à l'un des petits
mots ; la troisième condition est que la chaîne ne commence ni ne
finisse par *deux* petits mots.

Ainsi, sur les chaînes suivantes, le résultat ne devrait pas être le
même entre les deux scripts :
"-une-chaine-qui-commence-par-un-tiret"
"une-chaine-qui-finit-par-un-tiret-"
"-une-chaine-qui-commence-et-finit-par-un-tiret-"
"au"
"des-l-aube-a-l-heure-ou-blanchit-la-campagne"
"bouge-bouge-bouge-de-la"

Par ailleurs, bien que le résultat soit le même entre les deux scripts,
je ne suis pas sûr qu'il soit celui souhaité par Stéphane lorsque deux
petits mots se suivent à l'intérieur d'une chaîne :
"le-village-au-fond-de-la-vallee"
-> "village-fond-la-vallee" et pas "village-fond-vallee"

Cordialement,
--
Olivier Miakinen
Pierre Maurette
2013-05-13 15:37:49 UTC
Permalink
Olivier Miakinen :

[...]
Post by Olivier Miakinen
Par ailleurs, bien que le résultat soit le même entre les deux scripts,
je ne suis pas sûr qu'il soit celui souhaité par Stéphane lorsque deux
"le-village-au-fond-de-la-vallee"
-> "village-fond-la-vallee" et pas "village-fond-vallee"
Pour ce cas, il me semble qu'une rustine serait d'appliquer le
preg_replace() plusieurs fois. Tant que "ça matche".
Ce matin j'avais vu le truc et fait le test sur implode('-',
$petitsmots).
--
Pierre Maurette
Olivier Miakinen
2013-05-13 16:16:36 UTC
Permalink
Post by Pierre Maurette
Post by Olivier Miakinen
Par ailleurs, bien que le résultat soit le même entre les deux scripts,
je ne suis pas sûr qu'il soit celui souhaité par Stéphane lorsque deux
"le-village-au-fond-de-la-vallee"
-> "village-fond-la-vallee" et pas "village-fond-vallee"
Pour ce cas, il me semble qu'une rustine serait d'appliquer le
preg_replace() plusieurs fois. Tant que "ça matche".
Oui. Une méthode plus directe, mais plus difficile à lire pour qui
maîtrise mal les regexp, serait d'utiliser les assertions.
Pierre Maurette
2013-05-13 17:40:02 UTC
Permalink
Post by Olivier Miakinen
Post by Pierre Maurette
Post by Olivier Miakinen
Par ailleurs, bien que le résultat soit le même entre les deux scripts,
je ne suis pas sûr qu'il soit celui souhaité par Stéphane lorsque deux
"le-village-au-fond-de-la-vallee"
-> "village-fond-la-vallee" et pas "village-fond-vallee"
Pour ce cas, il me semble qu'une rustine serait d'appliquer le
preg_replace() plusieurs fois. Tant que "ça matche".
Oui. Une méthode plus directe, mais plus difficile à lire pour qui
maîtrise mal les regexp, serait d'utiliser les assertions.
La rustine que je proposais - même pas vraiment d'ailleurs - est en
fait assez poreuse, et même toute pourrite. Elle débouche sur du non
maintenable puisque basée sur le fait que '-blah-' est remplacé par '-'
et rien d'autre. Il ne semble pas aberrant de décider un jour de
remplacer par '', '_', '.', etc. Il vaut mieux faire du propre tout de
suite que plus tard dans l'urgence.
--
Pierre Maurette
Olivier Miakinen
2013-05-14 16:53:58 UTC
Permalink
Post by Olivier Miakinen
Oui. Une méthode plus directe, mais plus difficile à lire pour qui
maîtrise mal les regexp, serait d'utiliser les assertions.
[...] Il vaut mieux faire du propre tout de suite que plus tard dans
l'urgence.
D'accord. Alors voici ce que je propose.

$lsMasque = array(
'/(^|-)(au|de|du|des|en|l|le|la|les)(?=-|$)/',
'/^-/'
);
$lsUrl = preg_replace($lsMasque, '', $lsUrl);

Avec l'hypothèse qu'il n'y a jamais de trait d'union à conserver
en début de chaîne, ça devrait fonctionner.

Pierre Maurette
2013-05-13 07:32:28 UTC
Permalink
Post by Stéphane Santon
Bonjour,
Pour le calcul d'une url, je désire filtrer les petits mots de mon choix dans
- placés en début de chaine et suivis d'un tiret,
- placés en fin de chaine et précédés d'un tiret,
- placés dans la chaine et entourés d'un tiret.
Voici ce que je fais et qui fonctionne.
$lsMasque = array(
'(^au-|^de-|^du-|^des-|^en-|^l-|^le-|^la-|^les-)',
'(-au-|-de-|-du-|-des-|-en-|-l-|-le-|-la-|-les-)',
'(-au$|-de$|-du$|-des$|-en$|-l$|-le$|-la$|-les$)'
);
$lsUrl = preg_replace( $lsMasque, array('','-',''), $lsUrl);
Mais y aurait-il plus simple ?
Je pratique peu les expressions rationnelles, et surtout pas en Php.
C'est d'ailleurs parce que je le regrette que je lis les messages de ce
groupe, en tant qu'exercice ;-)

Votre code me semble lisible, et maintenable, c'est lié. On imagine
qu'il est sans doute factorisable un chouïa. Je saurais faire un truc
en Python, en Php, en me contentant de bricoler sur du texte, on peut
peut-être envisager un truc comme:

$petitsmots = array(
'au', 'de', 'du', 'des', 'en', 'l', 'le', 'la', 'les'
);
$petitsmots = implode('|', $petitsmots);
$lsMasque = array(
'(^('.$petitsmots.')-)',
'(-('.$petitsmots.')-)',
'(-('.$petitsmots.')$)'
);
--
Pierre Maurette
Olivier Miakinen
2013-05-13 08:36:51 UTC
Permalink
[...] en Php, en me contentant de bricoler sur du texte, on peut
$petitsmots = array(
'au', 'de', 'du', 'des', 'en', 'l', 'le', 'la', 'les'
);
$petitsmots = implode('|', $petitsmots);
$lsMasque = array(
'(^('.$petitsmots.')-)',
'(-('.$petitsmots.')-)',
'(-('.$petitsmots.')$)'
);
Oui, c'est aussi une bonne solution.

Encore plus simple :

$petitsmots = "(au|de|du|des|en|l|le|la|les)";
$lsMasque = array(
'^'.$petitsmots.'-',
'-'.$petitsmots.'-',
'-'.$petitsmots.'$'
);

Voire, si l'on est au clair avec la syntaxe des noms de variables et de
l'interprétation entre guillemets doubles :

$lsMasque = array(
"^$petitsmots-",
"-$petitsmots-",
"-$petitsmots$"
);
Loading...