J'ai le modèle suivant String : "Hello [Name] Please find attached [Invoice Number] which is due on [Due Date]"
.
J'ai également des variables de type String pour le nom, le numéro de facture et la date d'échéance. Quelle est la meilleure façon de remplacer les tokens du modèle par les variables ?
(Notez que si une variable contient un jeton, elle ne doit PAS être remplacée).
EDIT
Avec les remerciements de @laginimaineb et @alan-moore, Voici ma solution :
public static String replaceTokens(String text,
Map<String, String> replacements) {
Pattern pattern = Pattern.compile("\\[(.+?)\\]");
Matcher matcher = pattern.matcher(text);
StringBuffer buffer = new StringBuffer();
while (matcher.find()) {
String replacement = replacements.get(matcher.group(1));
if (replacement != null) {
// matcher.appendReplacement(buffer, replacement);
// see comment
matcher.appendReplacement(buffer, "");
buffer.append(replacement);
}
}
matcher.appendTail(buffer);
return buffer.toString();
}
0 votes
Une chose à noter, cependant, est que StringBuffer est le même que StringBuilder juste synchronisé. Cependant, puisque dans cet exemple vous n'avez pas besoin de synchroniser la construction de la chaîne, il est préférable d'utiliser StringBuilder (même si l'acquisition de verrous est une opération dont le coût est presque nul).
1 votes
Malheureusement, vous devez utiliser StringBuffer dans ce cas ; c'est ce que les méthodes appendXXX() attendent. Elles existent depuis Java 4, et StringBuilder n'a pas été ajouté avant Java 5. Comme vous l'avez dit, ce n'est pas un problème majeur, juste ennuyeux.
4 votes
Une dernière chose : appendReplacement(), comme les méthodes replaceXXX(), recherche les références de groupes de capture comme $1, $2, etc. et les remplace par le texte des groupes de capture associés. et les remplace par le texte des groupes de capture associés. Si votre texte de remplacement contient des signes de dollar ou des barres obliques inverses (qui sont utilisées pour échapper aux signes de dollar), vous pourriez avoir un problème. Le moyen le plus simple d'y remédier est de diviser l'opération d'ajout en deux étapes, comme je l'ai fait dans le code ci-dessus.
0 votes
Alan - très impressionné que vous ayez repéré cela. Je ne pensais pas qu'un problème aussi simple serait si difficile à résoudre !
0 votes
Utiliser java.sun.com/javase/6/docs/api/java/util/regex/
0 votes
FYI - Spring's UriTemplate.expand(Object...) utilise exactement le code ci-dessus, à l'exception du correctif ajouté par @AlanMoore . static.springsource.org/spring/docs/3.0.x/javadoc-api/org/
0 votes
Wow, c'est très, très cool. Une solution propre, minimale, efficace et complète. Merci à tous. Un des rares exemples où les regexp ont un sens.
0 votes
Voir
java.text.MessageFormat.format("Foo {} {}", "bar", 1);
1 votes
Note : les méthodes surchargées avec StringBuilder ont été ajoutées à Matcher dans java9. À partir de Java9, vous voudrez utiliser StringBuilder au lieu de StringBuffer.