IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

Remplacer un caractère à une position donnée dans une String


Sujet :

Langage Java

  1. #1
    Membre du Club
    Inscrit en
    Juin 2005
    Messages
    139
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 139
    Points : 59
    Points
    59
    Par défaut Remplacer un caractère à une position donnée dans une String
    Bonjour,

    J'ai réfléchi cet après midi a un problème et j'avoue que je suis bloqué.
    imaginons j'ai:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    String s = "('l'installation de la cuisine à l'entrée ')";
    je voudrai juste changer les simples quotes qui sont entre parenthèses c'est a dire l'installation de la cuisine à l’entrée.
    les autres cotes simples après la parenthèse ouvrante et avant la parenthèse fermante jy touche pas.
    c'est à dire je veux ça à la fin :

    "('l''installation de la cuisine à l''entrée ')"; (j'ai mis une double simple quote pour l'installation et pour l'entrée.

    Merci infiniment

  2. #2
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 557
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 557
    Points : 21 616
    Points
    21 616
    Par défaut
    Eh ben... C'est pas facile-facile, en fait. Il y a plusieurs manières d'aborder le problème. Je t'en propose une simple à comprendre, à trois étape :

    1 - Extraire le texte sur lequel faire des modification

    À l'aide d'une regex qui reconnaît les parenthèses de début et de fin, et surtout capture tout ce qu'il y a entre.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    String internal;
    Matcher matcher = Pattern.compile("\\('(.*)'\\)").matcher(s);
    if(matcher.matches()) {
      internal = matcher.group(1); // récupérer ce que la regex a trouvé entre parenthèses.
    } else {
      throw new IllegalArgumentException("Impossible de traiter la String de format inconnu : " + s);
    }
    2 - Remplacer les caractères

    Maintenant que les caractères que tu ne voulais pas toucher ne sont plus là, c'est tout simple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    internal = internal.replaceAll("'", "''");
    3 - Remettre entre parenthèses

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    String result = "(" + internal + ")";
    Conclusion -

    c'est pas trop long, ça s'adapte bien à la plupart des cas, et c'est facile à comprendre.
    Surtout si l'étape 1 est mise dans une méthode qui porte un nom genre private static String extractInternalText(String s) {.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 885
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 885
    Points : 6 618
    Points
    6 618
    Par défaut
    Avec une expression régulière, en utilisant l'ancre \G qui marque la position après la dernière correspondance.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    String s = "('l'installation de la cuisine à l'entrée ')";
     
    s = s.replaceAll("((?:\\G(?!\\A)|\\(')[^']*)'(?!\\))", "$1@");
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  4. #4
    Membre du Club
    Inscrit en
    Juin 2005
    Messages
    139
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 139
    Points : 59
    Points
    59
    Par défaut
    Merci CosmoKnacki ,

    C'est ce qu'il me fallait.
    J'ai choisi la deuxieme solution.
    par contre est ce que tu peux m'expliquer vite fait les expressions regulieres?
    Merci infiniment.
    bonne soirée

  5. #5
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 885
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 885
    Points : 6 618
    Points
    6 618
    Par défaut
    Le problème c'est que ça ne s'explique pas trop "vite fait", c'est pour ça que thelvin t'a proposé une solution simple ne faisant pas appel à des notions trop avancées de regex.

    Je vais te décrire le fonctionnement.

    Une des utilisations classique de l'ancre \G est justement de trouver plusieurs occurrences d'une sous-chaîne (ou d'une sous-pattern) entre deux bornes. Il s'agit d'une pattern à double entrée.

    quelques éléments:

    L'ancre \G correspond soit au début de la chaîne, soit à la position après la dernière correspondance de la pattern. Donc écrire \G(?!\A) revient à limiter la signification de \G à la position après la dernière correspondance de la pattern en excluant \A qui n'est rien d'autre que l'ancre de début de chaîne.

    Remarque: ça peut s'écrire dans n'importe quel sens, ce sont des "zero-width assertions" (bref, des indications qui ne "mangent" pas de caractères), soit: (?!\A)\G, \G(?<!\A), (?<!\A)\G, c'est kif-kif bourricot, toutes ces assertions n'ont pas de largeur, donc pas d'ordre.


    les deux entrées:

    La pattern commence par une alternative à deux branches:
    • La première branche s'occupe des correspondances consécutives à la correspondance précédente (d'où le \G).
    • La seconde s'occupe du point d'entrée (la borne d'ouverture), c'est à dire dans ce cas précis de ('. C'est par cette branche que se fera la première correspondance.


    fonctionnement:

    Au départ, la première branche échoue systématiquement, car il n'y a pas eu de correspondance avant. La deuxième branche (le point d'entrée) réussit quand (' est trouvé.

    Une fois cette réussite, on sort de l'alternative entre les deux branches et on continue jusqu'à ce qu'il n'y ait plus de caractères qui ne soient pas des simple quotes avec [^']* (pour atteindre le simple quote suivant potentiel). On sort alors du groupe de capture pour trouver le simple quote à remplacer. On vérifie avec un test avant négatif (negative lookahead) (?!\\)) qu'il n'est pas suivi d'une parenthèse fermante. (ce qui, dans le cas contraire, voudrait dire qu'il est le simple quote faisant partie de la borne de fermeture.)

    À ce stade la pattern réussit pour la première fois. Les caractères entre (' et le premier simple quote ont été capturés par le groupe 1. Donc on remplace le tout par le contenu du groupe 1 $1 et le caractère voulu @.

    Mais ça ne s'arrête pas là, car la méthode replaceAll (comme son nom l'indique) continue à parcourir la chaîne à la recherche d'autres correspondances. Seulement maintenant, il y a eu une correspondance, ce qui va permettre d'emprunter la première branche pour l'éventuelle correspondance suivante.

    Cette correspondance suivante devra être collée à la précédente (à cause de \G) pour pouvoir emprunter la première branche. Puis, une fois l'alternative entre les deux branches passée, c'est le même scénario. On atteint le simple quote suivant avec [^']*, on trouve le simple quote, on vérifie qu'il n'y a pas de parenthèse fermante. La pattern réussit, on remplace.

    On continue ainsi de suite en empruntant la première branche, jusqu'à ce qu'il n'y ait plus de simple quotes. (c'est pour cette raison que je l'ai placée en premier, car c'est la plus répétée.)

    la fin:

    Quand on atteint le dernier simple quote (placé avant la parenthèse fermante), le test avant négatif (negative lookahead) (?!\\)) fait échouer la pattern. Ce simple quote n'est donc pas remplacé.
    Pour que les simples quotes soient de nouveau remplacés, il faut que la deuxième branche de la pattern soit empruntée pour recommencer ce scénario.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  6. #6
    Membre du Club
    Inscrit en
    Juin 2005
    Messages
    139
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 139
    Points : 59
    Points
    59
    Par défaut
    Merci à tous les deux.
    J'ai du mal avec les expressions regulieres en java.
    Je vais me pencher dessus.
    juste un petit point que j'ai omis involontairement c'est que ma chaine commence par
    "upper('ici n'importe quelle cha'ine av'ec des apo'strophes simples')"
    L'expression reguliere que vous m'avez passé marche que sur les patterns sans le mot upper devant.
    cordialement

  7. #7
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 885
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 885
    Points : 6 618
    Points
    6 618
    Par défaut
    Pour être précis, la pattern fonctionne pour n'importe quelle sous-chaîne entre (' et ') quelque soit ce qu'il y ait avant.

    Si maintenant tu souhaites limiter l'action de la pattern aux sous-chaînes commençant par upper(', il suffit de l'indiquer dans la pattern.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  8. #8
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 886
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 886
    Points : 3 725
    Points
    3 725
    Par défaut
    Salut,

    Je me suis intéressé à ce fil mais je n'ai pas compris le problème... Si "('" et "')" se trouve toujours respectivement au début et à la fin de la String alors pourquoi on ne ferait pas juste appel à la fonction "String substring(int beginIndex, int endIndex)" pour extraire la partie entre "('" et "')" ?

    Quelque chose doit m'échapper...

    Je vais quand même essayer de comprendre vos réponses qui ont l'air instructives...

  9. #9
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 557
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 557
    Points : 21 616
    Points
    21 616
    Par défaut
    Citation Envoyé par Beginner. Voir le message
    Je me suis intéressé à ce fil mais je n'ai pas compris le problème... Si "('" et "')" se trouve toujours respectivement au début et à la fin de la String alors pourquoi on ne ferait pas juste appel à la fonction "String substring(int beginIndex, int endIndex)" pour extraire la partie entre "('" et "')" ?

    Quelque chose doit m'échapper...
    Ben justement tifsa nous explique qu'en réalité il peut y avoir des trucs avant, genre en réalité "upper(' du texte ')".

    ... Et CosmoKnacki et moi-même, en voyant la question et avec l'habitude, nous nous doutions bien qu'il lui fallait quelque chose d'un peu souple . La question est posée avec un certain niveau de maîtrise, qui laisse penser qu'il aurait forcément su faire la solution à substring(), mais que cela ne le satisfait pas. Pas difficile d'imaginer pourquoi.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  10. #10
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 886
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 886
    Points : 3 725
    Points
    3 725
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Ben justement tifsa nous explique qu'en réalité il peut y avoir des trucs avant, genre en réalité "upper(' du texte ')".

    ... Et CosmoKnacki et moi-même, en voyant la question et avec l'habitude, nous nous doutions bien qu'il lui fallait quelque chose d'un peu souple . La question est posée avec un certain niveau de maîtrise, qui laisse penser qu'il aurait forcément su faire la solution à substring(), mais que cela ne le satisfait pas. Pas difficile d'imaginer pourquoi.
    Si les trucs avant sont toujours les mêmes on peut encore utiliser substring() mais j'ai bien compris que vous avez voulu donner des réponses qui fonctionnent même si il y a des trucs variables avant "('" et aprés "')".

    Cela peut servir d'exemple instructif...

Discussions similaires

  1. Réponses: 21
    Dernier message: 22/01/2012, 02h19
  2. Recherche des données dans une BD ou dans une List
    Par mesken dans le forum Hibernate
    Réponses: 3
    Dernier message: 15/05/2011, 16h45
  3. [XL-2003] Récupération des données dans une base à partir d'une valeur donnée
    Par mandrake57 dans le forum Macros et VBA Excel
    Réponses: 19
    Dernier message: 01/04/2011, 14h33
  4. Réponses: 9
    Dernier message: 10/02/2010, 18h30
  5. Réponses: 6
    Dernier message: 13/11/2009, 16h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo