[Regexp] StringIndexOutOfBoundsException dans String.replaceAll()
Bonjour à tous,
Je viens de passer de longues minutes à m'arracher les quelques cheveux qu'il me restaient à cause d'un contenu de chaine de remplacement ... :mur:
Voici le cas "critique" qui peut faire que vos collègues fassent appel aux gentils messieurs en blouses blanches.
Le but : remplacer toutes les occurences de "{modele}" par une chaine saisie par l'utilisateur.
Code:
1 2 3 4 5
| public String test(String valeur) {
String source = "Voici un texte avec {modele} à l'intérieur...";
String resultat = source.replaceAll("\\{modele\\}", valeur);
return resultat;
} |
Dans presque tous les cas de contenu de "valeur" tout se passe bien
Code:
1 2
| test("azerty") -> "Voici un texte avec azerty à l'intérieur..."
test("a.z?e!r^t[y") -> "Voici un texte avec a.z?e!r^t[y à l'intérieur..." |
Il y a par contre au moins 2 cas qui posent problème en provoquant une StringIndexOutOfBoundsException.
Code:
1 2
| test("$") -> An exception occurred: java.lang.StringIndexOutOfBoundsException
test("\\") -> An exception occurred: java.lang.StringIndexOutOfBoundsException |
par contre
Code:
1 2
| test("$".replaceAll("\\$","\\\\\\$") -> "Voici un texte avec $ à l'intérieur..."
test("\\".replaceAll("\\\\","\\\\\\\\") -> "Voici un texte avec \ à l'intérieur..." |
Notez bien que dans le cas du $ il y a 6 \.
Donc si je place cet encodage dans ma fonction on obtient :
Code:
1 2 3 4 5 6
| public String test(String valeur) {
String source = "Voici un texte avec {modele} à l'intérieur...";
String valeur_encodee = valeur.replaceAll("\\\\","\\\\\\\\").replaceAll("\\$","\\\\\\$");
String resultat = source.replaceAll("\\{modele\\}", valeur_encodee);
return resultat;
} |
:aie:
Suite à la réponse #5 de Arcadia, voici le code équivalent avec "java.util.Matcher.quoteReplacement()" :
Code:
1 2 3 4 5 6
| public String test(String valeur) {
String source = "Voici un texte avec {modele} à l'intérieur...";
String valeur_encodee = Matcher.quoteReplacement(valeur);
String resultat = source.replaceAll("\\{modele\\}", valeur_encodee);
return resultat;
} |
devyan.