Remplacement nombres dans string
Je dois parser une string qui peut avoir un contenu du type :
informazione
3 twitter.com/signupcf53.html
2 play.google.com/store/apps/detailsc2bc.html
1 arcmc.hypotheses.org/category/veille-scientifique/portails.html
1 www.addthis.com/bookmarkda7d.html
=7
(0)
Il faut supprimer les nombres suivis d'un espace, les trucs du type =nombre avec nombre entre 0 et 1000000 exclut, même chose pour (nombre)
mais il faut absolument que les nombres dans les urls ne soient pas supprimés
Par exemple, dans twitter.com/signupcf53.html 53 doit rester
J'ai essayé ça :
infos[1] = infos[1].replaceAll("[0-9] ","");
infos[1] = infos[1].replaceAll("=[0-9]","");
infos[1] = infos[1].replaceAll("([0-9])","");
infos[1] = infos[1].replaceAll(" ","");
infos[1] = infos[1].replaceAll("=","");
infos[1] = infos[1].replaceAll("\\(","");
infos[1] = infos[1].replaceAll("\\)","");
mais ça ne marche pas
Merci d'avance, j'ai vraiment besoin que ça marche...
6 réponses
Problème central: concevoir une expression régulière en Java qui supprime les nombres hors des URL tout en préservant ceux présents dans les adresses. Des réponses variées proposent des patterns pour ignorer les chiffres internes aux URL, traiter les chiffres entourés de signes et parenthèses, et filtrer les nombres suivis d'un espace ou d'un signe égal. Des résultats montrent des échecs: des chiffres hors URL comme =9 ou =101, des espaces après le signe égal, ou des cas où les chiffres entre 1 et 999999 ne sont pas correctement distingués. En cas de besoin, certains conseillent d'utiliser plusieurs passes ou trois expressions distinctes et de s'appuyer sur des ressources externes comme des tutoriels Regex ou des tests en ligne.
-
Bonjour
je ne sais pas comment s'implémente une Regex en Java, mais ça peut répondre à ton besoin.
Un exemple icihttp://regexstorm.net/tester?p=%28%3f%3a%5cd%2b+%29%7c%28%3f%3a%28%3f%3c%3d%5c%28%29%5cd%2b%28%3f%3d%5c%29%29%29&i=3+twitter.com%2fsignupcf53.html+%0d%0a2+play.google.com%2fstore%2fapps%2fdetailsc2bc.html+%0d%0a1+arcmc.hypotheses.org%2fcategory%2fveille-scientifique%2fportails.html+%0d%0a1+www.addthis.com%2fbookmarkda7d.html+%0d%0a%3d7+%0d%0a%280%29+&r=remplacement
Cet exemple ne tient pas compte de la contrainteentre 0 et 1000000 exclut
mais ça peut se gérer.
Click sur l'onglet "Context" pour voir le résultat final
-
Voilà qui fait
http://regexstorm.net/tester?p=%28%3f%3a%28%3f%3c%3d%5b%5e%5cd%5d%7c%5e%29%28%5b1-9%5d%7c%5cd%7b2%2c6%7d%29+%29%7c%28%28%3f%3c%3d%5c%28%29%28%5b1-9%5d%7c%5cd%7b2%2c6%7d%29%28%3f%3d%5c%29%29%29&i=3+twitter.com%2fsignupcf53.html+%0d%0a2+play.google.com%2fstore%2fapps%2fdetailsc2bc.html+%0d%0a1+arcmc.hypotheses.org%2fcategory%2fveille-scientifique%2fportails.html+%0d%0a1+www.addthis.com%2fbookmarkda7d.html+%0d%0a%3d7+%0d%0a%280%29+%0d%0a%283%29%0d%0a123456+1000000+100000+999999+%28999999%29&r=remplacement
-
@Utilisateur anonymeMerci de la réponse,
J'ai essayé de modifier pour supprimer n'importe quel nombre qui n'est pas dans l'URL, ça semble fonctionner.
Pouvez-vous expliquer comment fonctionne la syntaxe des regexs ?
Par exemple, il faudrait rajouter quoi, pour supprimer les = et les parenthèses ouvrantes et fermantes ?
-
-
Alors non, je ne vais pas t'expliquer toutes les syntaxes possibles, y'a des tutos tout faits pour ça
Celui là est orienté vers php, vers il me semble bien introduire la chose
https://www.lucaswillems.com/fr/articles/25/tutoriel-pour-maitriser-les-expressions-regulieres
Celui-ci concerne l'implémentation dans Java
https://cyberzoide.developpez.com/tutoriels/java/regex/
Sur RegexStorm (et beaucoup d'autres sites de tests en ligne), tu as des exemples (page Référence)
Pour les parenthèses et les = je pensais qu'il fallait les exclure
http://regexstorm.net/tester?p=%28%3f%3a%28%3f%3c%3d%5b%5e%5cd%5d%7c%5e%29%3d%3f%28%5b1-9%5d%7c%5cd%7b2%2c6%7d%29+%29%7c%28%5c%28%28%5b1-9%5d%7c%5cd%7b2%2c6%7d%29%5c%29%29&i=3+twitter.com%2fsignupcf53.html+%0d%0a2+play.google.com%2fstore%2fapps%2fdetailsc2bc.html+%0d%0a1+arcmc.hypotheses.org%2fcategory%2fveille-scientifique%2fportails.html+%0d%0a1+www.addthis.com%2fbookmarkda7d.html+%0d%0a%3d7+%0d%0a%280%29+%0d%0a%283%29%0d%0a123456+1000000+100000+999999+%28999999%29&r=remplacement
Quand j'étais petit, la mer Morte n'était que malade.
George Burns -
Poste un texte représentatif.
-
-
Là ça marche s'il y a un espace, une fin de ligne ou la fin du texte, mais si c'est du texte, je ne peux pas savoir si on est dans une URL ou pas.
http://regexstorm.net/tester?p=%28%3f%3a%28%3f%3c%3d%5b%5e%5cd%5d%7c%5e%29%3d%3f%28%5b1-9%5d%7c%5cd%7b2%2c6%7d%29%28%3f%3d%28+%7c%5cr%7c%24%29%29%29%7c%28%5c%28%28%5b1-9%5d%7c%5cd%7b2%2c6%7d%29%5c%29%29&i=3+twitter.com%2fsignupcf53.html+%0d%0a2+play.google.com%2fstore%2fapps%2fdetailsc2bc.html+%0d%0a1+arcmc.hypotheses.org%2fcategory%2fveille-scientifique%2fportails.html+%0d%0a1+www.addthis.com%2fbookmarkda7d.html+%0d%0a%3d7+%0d%0a%280%29+%0d%0a%283%29%0d%0a123456+1000000+100000+999999+%28999999%29%0d%0a%3d101+coucou%0d%0a%3d101coucocu%0d%0a%3d101%0d%0a%3d101&r=remplacement
-
-
ModérateurBonjour,
Il n'y a pas vraiment de spécificités d'expressions régulières en Java ce sont les même règles que partout ailleurs (avec peut-être quelques ajouts).
La documentation est sur la classe Pattern (c'est indiqué dans la javadoc de la méthode replaceAll que tu as utilisé)
https://docs.oracle.com/javase/9/docs/api/java/util/regex/Pattern.html
Cependant, est-ce bien utile de faire une expression régulière ici ?
Tu as un nombre, un espace, et tu prends tout le reste, donc un indexOf pour trouver l'espace, un substring pour récupérer la fin et c'est bon...
String line = "42 blabla17toto"; int n = line.indexOf(" "); line = line.substring(n+1); // blabla17toto-
-
Modérateur@Utilisateur anonymeSi je me base juste sur les exemples donnés, les autres cas concernent des lignes qui ne commencent pas par des nombres et qui sont donc à ignorer.
Il faut donc d'enrichir un petit peu pour vérifier que la première partie est un nombre ou pas, mais je pense que ça reste plus simple (et peut-être même plus performant) qu'une expression régulière.
String line = "42 blabla17toto"; int n = line.indexOf(" "); if (n > 0) { String header = line.substring(0, n); try { int headerPart = Integer.parseInt(header); if (headerPart > 0 && headerPart < 1000000) { String result = line.substring(n + 1); // ... } } catch (RuntimeException e) { // header n'est pas un int } }
Après oui, on peut sûrement le faire avec une expression régulière, je propose^\d+ ([^\d].*)
mais j'ai peut-être effectivement mal compris la question... -
-
Mon fichier est composé de lignes comme celles-ci :
1 www.umrespace.org/credits.htm
1 www.unicaen.fr/recherche/mrsh/forge.html
1 www.univ-angers.fr/fr/recherche/actualites/les-territoires-du-cinema/janvier.html
1 www.viamichelin.fr/tpl/fr/divers/htm/legalnotice.htm
1 www.zdnet.fr/actualites/skype-pret-a-changer-pour-gagner-sa-place-dans-les-entreprises-39361540.htm
1 www2.cnrs.fr/presse/communique/3705.htm
1 www2.cnrs.fr/presse/communique/3709.htm
1 www2.cnrs.fr/presse/communique/3711.htm
1 www2.cnrs.fr/presse/communique/3713.htm
1 www2.cnrs.fr/presse/communique/3715.htm
1 www2.cnrs.fr/presse/communique/3717.htm
1 www2.cnrs.fr/presse/communique/3719.htm
1 www2.cnrs.fr/presse/communique/3723.htm
=1726
(0)
Je veux supprimer les "1 " (ça peut aussi être 25 comme 46)
et les "=2736" et "(0)" mais ne pas toucher aux URLs, dans ma version actuelle, j'ai un problméme avec les lignes du type 1 www.legifrance.gouv.fr/affichTexte.do;jsessionid=73323E2953E34259F5F3E45F69925E1F537a.html
ou le "=" de l'URL est supprimé et ça fait planter mon moteur de recherche
Au niveau du filtrage, j'ai mis ça :
infos[1] = infos[1].replaceAll("(?:(?<=[^\\d]|^)([0-9]|\\d*) )|((?<=\\()([0-9]|\\d*)(?=\\)))","");
infos[1] = infos[1].replaceAll(" ","");
infos[1] = infos[1].replaceAll("=","");
infos[1] = infos[1].replaceAll("\\(","");
infos[1] = infos[1].replaceAll("\\)","");
infos[1] = infos[1].replaceAll("^[0-9]",""); -
-
-
ModérateurPour le challenge, je viens de tester les deux codes (le mien et celui de Whismeril), les deux donnent le même fichier texte en sortie (à un espace près... car "=1726 " est remplacé chez moi par "" contre " " pour Whismeril)
Entrée :1 www.umrespace.org/credits.htm
1 www.unicaen.fr/recherche/mrsh/forge.html
1 www.univ-angers.fr/fr/recherche/actualites/les-territoires-du-cinema/janvier.html
1 www.viamichelin.fr/tpl/fr/divers/htm/legalnotice.htm
1 www.zdnet.fr/actualites/skype-pret-a-changer-pour-gagner-sa-place-dans-les-entreprises-39361540.htm
1 www2.cnrs.fr/presse/communique/3705.htm
1 www2.cnrs.fr/presse/communique/3709.htm
1 www2.cnrs.fr/presse/communique/3711.htm
1 www2.cnrs.fr/presse/communique/3713.htm
1 www2.cnrs.fr/presse/communique/3715.htm
1 www2.cnrs.fr/presse/communique/3717.htm
1 www2.cnrs.fr/presse/communique/3719.htm
1 www2.cnrs.fr/presse/communique/3723.htm
=1726
(0)
Sortie :www.umrespace.org/credits.htm
J'ai joué les deux codes sur un fichier texte de 500'000 lignes, et même si les temps sont assez aléatoires (accès I/O...), on peut quand même en déduire que les temps sont environ 5 fois plus long avec une regex (dans ce cas précis).
www.unicaen.fr/recherche/mrsh/forge.html
www.univ-angers.fr/fr/recherche/actualites/les-territoires-du-cinema/janvier.html
www.viamichelin.fr/tpl/fr/divers/htm/legalnotice.htm
www.zdnet.fr/actualites/skype-pret-a-changer-pour-gagner-sa-place-dans-les-entreprises-39361540.htm
www2.cnrs.fr/presse/communique/3705.htm
www2.cnrs.fr/presse/communique/3709.htm
www2.cnrs.fr/presse/communique/3711.htm
www2.cnrs.fr/presse/communique/3713.htm
www2.cnrs.fr/presse/communique/3715.htm
www2.cnrs.fr/presse/communique/3717.htm
www2.cnrs.fr/presse/communique/3719.htm
www2.cnrs.fr/presse/communique/3723.htm
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.function.Function; public class Test { public static long test(String src, String dst, Function<String, String> mapper) throws IOException { long n = System.nanoTime(); Files.write(Paths.get(dst), (Iterable<String>) Files.lines(Paths.get(src)).map(mapper)::iterator); return System.nanoTime() - n; } public static String testWhismeril(String line) { return line.replaceAll("(=([1-9]|\\d{2,6})\\b)|(\\b([1-9]|\\d{2,6}) )|(\\(\\d+\\))", ""); } public static String testKx(String line) { int n = line.indexOf(" "); if (n > 0) { String header = line.substring(0, n); try { int headerPart = Integer.parseInt(header); if (headerPart > 0 && headerPart < 1000000) { return line.substring(n + 1); } } catch (RuntimeException e) { // header n'est pas un int } } return ""; } public static void main(String[] args) throws IOException { System.out.println(test("C:/test.txt", "C:/testKx.txt", Test::testKx)); // 191.178337 ms System.out.println(test("C:/test.txt", "C:/testWhismeril.txt", Test::testWhismeril)); // 665.538444 ms System.out.println(test("C:/test.txt", "C:/testKx.txt", Test::testKx)); // 57.867188 ms System.out.println(test("C:/test.txt", "C:/testWhismeril.txt", Test::testWhismeril)); // 268.716917 ms System.out.println(test("C:/test.txt", "C:/testKx.txt", Test::testKx)); // 35.440601 ms System.out.println(test("C:/test.txt", "C:/testWhismeril.txt", Test::testWhismeril)); // 252.767325 ms } }-
-
Modérateur@Utilisateur anonymeIl faut voir aussi qu'avec un replaceAll on n'utilise pas toute la puissance des expressions régulières, puisqu'on se limite à un seul groupe de capture, de plus Java va devoir reconstruire la regex à chaque ligne, ce qui va lui prendre du temps, alors que c'est toujours la même (mais il ne le sait pas).
Voici comment s'en sortir avec une vrai regex, compilée une seule fois au début.
private static final Pattern pattern = Pattern.compile("^(\\S+\\s)?(\\D.*)"); public static String testKx2(String line) { Matcher matcher = pattern.matcher(line); if (matcher.find() && matcher.group(1) != null) { return matcher.group(2); } else { return ""; } }
Le résultat est un meilleur, seulement 2x le temps de mon code sans regex, à comparer au 5x qu'on avait avec la grosse regex du replaceAll.
NB. Ici je ne gère pas le cas où l'entier est supérieur à 1000000 mais j'ai l'impression que c'est une propriété qui n'est pas discriminante pour le découpage (si on a un entier ce sera toujours un nombre inférieur à cette limite).
-
-
Merci pour votre aide, la fonction semble marcher maintenant.
Mais j'ai un autre problème : J'ai une autre fonction qui se charge de scanner un fichier composé de liens de pages et de liens vers la page qui mène à cette page (origine).
Normalement je devrais avoir 27394 pages dans la HashMap après scan, mais j'en ai que 27387.
J'ai essayé de faire des prints un peu partout pour voir ce qui se passe, mais ça semble pourtant bien fonctionner, mais le scan doit manquer des pages. J'ai passé 3 après-midi sur cette fonction (readWebPages(), de la classe SearchEngine) sans arriver à trouver le problème et j'aimerai bien le trouver.
Je mets les fichiers du projet dans un lien lien supprimé par la modération
Le code (pour éviter les robots trop curieux) 88cPvRc4
Les fichiers txt scannés sont dans le répertoire data du projet...-
-
@KXLe liens vers le zip ne suffit pas pour "le code" ?
-