Remplacement nombres dans string

Fermé
dd - Modifié le 2 nov. 2017 à 17:55
 dd - 4 nov. 2017 à 12:13
Bonsoir,

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...
A voir également:

6 réponses

Utilisateur anonyme
2 nov. 2017 à 19:01
Bonjour

je ne sais pas comment s'implémente une Regex en Java, mais ça peut répondre à ton besoin.

Un exemple ici
http://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 contrainte
entre 0 et 1000000 exclut
mais ça peut se gérer.
Click sur l'onglet "Context" pour voir le résultat final
0
Utilisateur anonyme
2 nov. 2017 à 19:35
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
0
dd > Utilisateur anonyme
2 nov. 2017 à 20:23
Merci 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 ?
0
Utilisateur anonyme
Modifié le 2 nov. 2017 à 20:33
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
0
J'ai essayé (?:(?<=[^\\d]|^)([1-9]|\\d*) )|((?<=\\()([1-9]|\\d*)(?=\\))) avec replaceAll, mais ça ne supprime pas les nombres quand ils ne sont pas dans l'URL, par exemple pour une ligne avec =9, il y a toujours le 9
0
Utilisateur anonyme
2 nov. 2017 à 21:17
Dans ton exemple, =7 est suivi d'un espace, ça m'a servit.
Si ça n'est pas le cas, il faut poster un exemple représentatif.

De plus cette syntaxe, exclut les = et les parenthèse et ne tient pas compte de 1 à 999999
0
désolé, y a pas d'espace après =nombre.

Le seul probleme restant est que la suppression de =nombre ne marche pas avec un nombre >9, =101 se transforme en 01
0
Utilisateur anonyme
2 nov. 2017 à 21:45
Poste un texte représentatif.
0
Utilisateur anonyme
3 nov. 2017 à 06:39
Ce que j'ai besoin de connaitre c'est ce qu'il y a derrière le nombre précédé d'un =
0
Utilisateur anonyme
3 nov. 2017 à 07:27
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
0
KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 020
2 nov. 2017 à 23:11
Bonjour,

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
0
Utilisateur anonyme
3 nov. 2017 à 06:05
Salut, c'est un peu plus compliqué, il y a les nombres suivis d'espaces, mais aussi les nombres précédés d'un = ou ceux entre parenthèses.
0
KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 020 > Utilisateur anonyme
3 nov. 2017 à 08:46
Si 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...
0
Utilisateur anonyme
Modifié le 3 nov. 2017 à 08:55
Niveau performance, faut essayer et comparer les durées d’exécution.
Sur un texte entier, j’ai généralement constaté une meilleure efficacité des regex, sur une seule ligne pas forcément.
0
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]","");


0
Utilisateur anonyme
Modifié le 3 nov. 2017 à 18:39
Tu veux supprimer (0), mais 0 n'est pas contenu entre 1 et 999999?
Et dans cet exemple il y a un espace après =1726.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 020
3 nov. 2017 à 19:43
Pour 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 
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

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).

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
    }
}
0
Utilisateur anonyme
3 nov. 2017 à 22:48
5 fois quand même!
Faut dire que la Regex à 3 pattern, c'est un peu tordu, il faudrait voir ce que ça donne avec 3 regex.
0
KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 020 > Utilisateur anonyme
4 nov. 2017 à 00:27
Il 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).
0
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...
0
KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 020
4 nov. 2017 à 12:00
Vu que ce n'est pas la même question, créé une nouvelle discussion, et postes ton code sur le site, c'est un forum communautaire, donc les réponses doivent être utiles à d'autres et s'ils n'ont pas la question (donc le code qui va avec) ça ne sert qu'à toi et ce n'est pas le but.
0
dd > KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024
4 nov. 2017 à 12:13
Le liens vers le zip ne suffit pas pour "le code" ?
0