Regex : trouver tous les mots de plus de 3 lettres entre deux autres mots [Résolu/Fermé]

Signaler
Messages postés
1
Date d'inscription
vendredi 22 mars 2019
Statut
Membre
Dernière intervention
22 mars 2019
-
Messages postés
14580
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
7 août 2020
-
Bonjour,

Je suis novice en Regex et je dois écrire (en java) une Regex pour trouver tous les mots de plus de 3 lettres entre deux mots données. .

Par exemple, je dois écrire une Regex qui trouve tous les mots de plus de 3 lettres qui se trouvent entre les mots "P(p)ig(s)" et "B(b)ird(s)" dans les phrases suivante :

Pigs are farm animals. Birds are not
My bird fly in his cage. My pig run in the garden.

Merci

5 réponses

Messages postés
3
Date d'inscription
mercredi 4 mars 2020
Statut
Membre
Dernière intervention
6 mars 2020

Bonjour,

Le but de ma réflexion n'était pas de remettre en question votre travail; au contraire vous étiez d'une grande aide pour moi et je vous remercie pour cela. Je voulais juste comprendre pourquoi le (?<=) ne marchait pas si j'enlevais" le ou"; si je laissais le (*.) ou si je rajoutais le "\\W*" pour la ponctuation par exemple "pigs;".

En tout les cas j'y travaille.
Merci beaucoup.
Messages postés
1
Date d'inscription
vendredi 22 mars 2019
Statut
Membre
Dernière intervention
23 mars 2019

Salut,
Je te conseil d'utiliser ce site pour apprendre / tester tes regexs <a href="https://regex101.com">https://regex101.com</a>
pour la tienne on doit être sur quelque chose du style:
(bird|pig)(s){0,1}(.*)([a-z]{3,*})(.*)(bird|pig)(s){0,1} avec un flag en no case et le tour est joué
Messages postés
14580
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
7 août 2020
559
Bonjour
Le conseil d’utiliser un site de test est très bon, et évite de poster une regex qui ne marche pas ;).

Celle-ci fonctionne
(?<=((birds?)|(pigs?)).*)\b[a-z]{3,}\b(?=.*((birds?)|(pigs?)))



Messages postés
3
Date d'inscription
mercredi 4 mars 2020
Statut
Membre
Dernière intervention
6 mars 2020

SVP, lorsque j'ai testé votre code sur Eclipse; il m'a déclencher une erreur: '
Look-behind group does not have an obvious maximum length', j'ai compris que le ?<= ne fonctionne pas avec (.*) il faut qu'il soit limité. Alors comment avez vous fait?
Merci.
Messages postés
14580
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
7 août 2020
559
BONJOUR

Comme le montre la capture, je l’ai fair sur un site de test.
Copie colle le lien ci dessous
http://regexstorm.net/tester?p=%28%3f%3c%3d%28%28birds%3f%29%7c%28pigs%3f%29%29.*%29%5cb%5ba-z%5d%7b3%2c%7d%5cb%28%3f%3d.*%28%28birds%3f%29%7c%28pigs%3f%29%29%29&i=Pigs+are+farm+animals.+Birds+are+not+%0d%0aMy+bird+fly+in+his+cage.+My+pig+run+in+the+garden.&o=i


Mais effectivement sur un autre site (regex101.com) elle ne fonctionne pas.

Cela celle proposée par 410gone ne fonctionne pas non plus sur regex101.

Messages postés
14580
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
7 août 2020
559 >
Messages postés
14580
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
7 août 2020

AU temps pour moi, quand je coche le langage JavaScript sur regex101, ma regex fonctionne aussi
https://regex101.com/r/piabvE/1
Messages postés
15975
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
8 août 2020
2 648
Pour que cela fonctionne en Java, il ne faut pas oublier de doubler les
\
et préciser que la regex doit être insensible à la casse (sinon la première ligne ne matchera pas).

Pattern pattern = Pattern.compile("(?<=((birds?)|(pigs?)).*)\\b[a-z]{3,}\\b(?=.*((birds?)|(pigs?)))",
    Pattern.CASE_INSENSITIVE);

String text = "Pigs are farm animals. Birds are not\n"
    + "My bird fly in his cage. My pig run in the garden.";

Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
    System.out.println(matcher.group(0));
}

Résultat :
are
farm
animals
fly
his
cage
Messages postés
14580
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
7 août 2020
559 >
Messages postés
15975
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
8 août 2020

Salut,

pour IgnoreCase ça avait été dit plus haut. Cependant, cela tolère biRd par exemple comme borne, si on ne veut que (B)bird et (P)ig
(?<=(([Bb]irds?)|([Pp]igs?)).*)\b[a-z]{3,}\b(?=.*(([Bb]irds?)|([Pp]igs?)))
Messages postés
3
Date d'inscription
mercredi 4 mars 2020
Statut
Membre
Dernière intervention
6 mars 2020

Bonjour,

Et merci pour vos réponses.
Effectivement si vous utilisez l'expression tel que vous avez décrit; cela fonctionne mais n'est pas totalement correcte puisqu'elle tolère des mots autres voulus; par exemple: birds are animals, also birds ------ le résultat va étre are animals et also; or c'est faux.
Et comme je voulez raffiner la recherche j'ai enlevé la partie qui vient après le ou, de (?<=(([Bb]irds?)|([Pp]igs?)).*) ce qui a engendré une erreur comme quoi le (?<=) ne tolère pas le *. et qu il faut que ça soit limitée.

Voila le pb que j ai eu.
Merci.
Messages postés
14580
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
7 août 2020
559
e résultat va étre are animals et also; or c'est faux.

c'était pas précisé qu'il fallait que les bornes soient différentes.
Messages postés
14580
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
7 août 2020
559
Quand tu
birds are animals, also birds ------ le résultat va étre are animals et also; or c'est faux.
pour moi c'est correct puisque animals et also sont des mots de plus de trois lettres compris entre et birds et birds.

Et comme je voulez raffiner la recherche j'ai enlevé la partie qui vient après le ou, de (?<=(([Bb]irds?)|([Pp]igs?)).*) ce qui a engendré une erreur comme quoi le (?<=) ne tolère pas le *. et qu il faut que ça soit limitée.


Les moteurs de regex sont un peu différents d'un langage à l'autre.
Par exemple, l'implémentation VBA ne permet pas de donner un nom à un groupe, ce qui est bien plus pratique que de compter les groupes pour savoir quel est l'index de celui que tu cherches.

Dans le cas présent, on a vu que sur Regex101 si on coche PHP, il y a une erreur, alors que sur Regexstorm qui utilise l'implémentation .Net ça fonctionne.
J'ai trouvé un site de test basé sur Java8 où il y a une erreur et un autre basé sur une version plus récente de Java où ça fonctionne.

J'ai essayé sur plein de sites, jusqu'à la réponse de KX, réponse que j'ai pensé résoudre le problème puisqu'il code en Java et a même posté le code complet.

Bref pendan mes différents tests j'ai eu 2 types d'erreurs, l'une disait que le "Zero-width positive lookbehind assertion" (que je traduirais par pré-requis) doit avoir une longueur fixe et l'autre erreur disait que le pré-requis doit avoir une longueur limitée.

Bref, on dirait qu'il y a 3 implémentations différentes pour les pré requis, la plus ancienne ne supportait qu'une longueur fixe, la seconde une longueur limitée et la plus récente peu importe.

Je pense donc cette erreur est due à ta version de Java (ou du moteur de regex) qui doit être ancienne.

Je voulais juste comprendre pourquoi le (?<=) ne marchait pas si j'enlevais" le ou"; si je laissais le (*.) ou si je rajoutais le "\\W*" pour la ponctuation par exemple "pigs;".

Sans les regex exactes que tu as essayé, je réponds dans le vide...
Pour le ou, si tu l'enlèves tu ne cherches plus qu'une seule borne donc tu ne captures plus entre pigs et birds par exemple.