util pattern online number matches example java regex templates

pattern - ¿Cómo reemplazar un conjunto de tokens en una cadena Java?



regex number java (14)

Con la Biblioteca de Apache Commons, puede simplemente usar Stringutils.replaceEach :

public static String replaceEach(String text, String[] searchList, String[] replacementList)

De la Stringutils.replaceEach :

Reemplaza todas las ocurrencias de cadenas dentro de otra cadena.

Una referencia nula pasada a este método es no operativa, o si cualquier "cadena de búsqueda" o "cadena para reemplazar" es nula, esa sustitución será ignorada. Esto no se repetirá. Para repetir reemplazos, llame al método sobrecargado.

StringUtils.replaceEach(null, *, *) = null StringUtils.replaceEach("", *, *) = "" StringUtils.replaceEach("aba", null, null) = "aba" StringUtils.replaceEach("aba", new String[0], null) = "aba" StringUtils.replaceEach("aba", null, new String[0]) = "aba" StringUtils.replaceEach("aba", new String[]{"a"}, null) = "aba" StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}) = "b" StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}) = "aba" StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte" (example of how it does not repeat) StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "dcte"

Tengo la siguiente cadena de plantilla: "Hello [Name] Please find attached [Invoice Number] which is due on [Due Date]" .

También tengo variables de cadena para el nombre, el número de factura y la fecha de vencimiento. ¿Cuál es la mejor manera de reemplazar los tokens en la plantilla con las variables?

(Tenga en cuenta que si una variable contiene un token, NO debe ser reemplazada).

EDITAR

Gracias a @laginimaineb y @ alan-moore, esta es mi solución:

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(); }


Depende de dónde se encuentren los datos reales que desea reemplazar. Es posible que tenga un mapa como este:

Map<String, String> values = new HashMap<String, String>();

que contiene todos los datos que pueden ser reemplazados. Luego puede iterar sobre el mapa y cambiar todo en la cadena de la siguiente manera:

String s = "Your String with [Fields]"; for (Map.Entry<String, String> e : values.entrySet()) { s = s.replaceAll("//[" + e.getKey() + "//]", e.getValue()); }

También podría iterar sobre la Cadena y encontrar los elementos en el mapa. Pero eso es un poco más complicado porque necesita analizar el String buscando el []. Podrías hacerlo con una expresión regular usando Pattern y Matcher.


Desafortunadamente, el cómodo método String.format mencionado anteriormente solo está disponible comenzando con Java 1.5 (que debería ser bastante estándar hoy en día, pero nunca se sabe). En lugar de eso, también podría usar la clase MessageFormat de Java para reemplazar los marcadores de posición.

Admite marcadores de posición con el formato ''{number}'', por lo que su mensaje se vería como "Hola {0} Encontrar adjunto {1} que vence el {2}". Estas cadenas se pueden externalizar fácilmente utilizando ResourceBundles (por ejemplo, para la localización con múltiples configuraciones regionales). El reemplazo se haría usando el método static''format ''de la clase MessageFormat:

String msg = "Hello {0} Please find attached {1} which is due on {2}"; String[] values = { "John Doe", "invoice #123", "2009-06-30" }; System.out.println(MessageFormat.format(msg, values));


En el pasado, he resuelto este tipo de problema con StringTemplate y Groovy Templates .

En última instancia, la decisión de utilizar un motor de plantillas debería estar basada en los siguientes factores:

  • ¿Tendrás muchas de estas plantillas en la aplicación?
  • ¿Necesita la capacidad de modificar las plantillas sin reiniciar la aplicación?
  • ¿Quién mantendrá estas plantillas? ¿Un programador de Java o un analista de negocios involucrado en el proyecto?
  • ¿Necesitará la capacidad de poner lógica en sus plantillas, como el texto condicional basado en valores en las variables?
  • ¿Necesitarás la posibilidad de incluir otras plantillas en una plantilla?

Si alguna de las opciones anteriores se aplica a su proyecto, consideraría utilizar un motor de plantillas, la mayoría de las cuales proporcionan esta funcionalidad, y más.



La forma más eficiente sería usar un matcher para encontrar continuamente las expresiones y reemplazarlas, luego agregar el texto a un generador de cadenas:

Pattern pattern = Pattern.compile("//[(.+?)//]"); Matcher matcher = pattern.matcher(text); HashMap<String,String> replacements = new HashMap<String,String>(); //populate the replacements map ... StringBuilder builder = new StringBuilder(); int i = 0; while (matcher.find()) { String replacement = replacements.get(matcher.group(1)); builder.append(text.substring(i, matcher.start())); if (replacement == null) builder.append(matcher.group(0)); else builder.append(replacement); i = matcher.end(); } builder.append(text.substring(i, text.length())); return builder.toString();


Mi solución para reemplazar tokens de estilo $ {variable} (inspirada por las respuestas aquí y por Spring UriTemplate):

public static String substituteVariables(String template, Map<String, String> variables) { Pattern pattern = Pattern.compile("//$//{(.+?)//}"); Matcher matcher = pattern.matcher(template); // StringBuilder cannot be used here because Matcher expects StringBuffer StringBuffer buffer = new StringBuffer(); while (matcher.find()) { if (variables.containsKey(matcher.group(1))) { String replacement = variables.get(matcher.group(1)); // quote to work properly with $ and {,} signs matcher.appendReplacement(buffer, replacement != null ? Matcher.quoteReplacement(replacement) : "null"); } } matcher.appendTail(buffer); return buffer.toString(); }


Podría intentar usar una biblioteca de plantillas como Apache Velocity.

http://velocity.apache.org/

Aquí hay un ejemplo:

import org.apache.velocity.VelocityContext; import org.apache.velocity.app.Velocity; import java.io.StringWriter; public class TemplateExample { public static void main(String args[]) throws Exception { Velocity.init(); VelocityContext context = new VelocityContext(); context.put("name", "Mark"); context.put("invoiceNumber", "42123"); context.put("dueDate", "June 6, 2009"); String template = "Hello $name. Please find attached invoice" + " $invoiceNumber which is due on $dueDate."; StringWriter writer = new StringWriter(); Velocity.evaluate(context, writer, "TemplateName", template); System.out.println(writer); } }

La salida sería:

Hello Mark. Please find attached invoice 42123 which is due on June 6, 2009.


Puede usar la biblioteca de plantillas para reemplazar plantillas complejas.

FreeMarker es una muy buena opción.

http://freemarker.sourceforge.net/

Pero para una tarea simple, hay una clase de utilidad simple que puede ayudarlo.

org.apache.commons.lang3.text.StrSubstitutor

Es muy poderoso, personalizable y fácil de usar.

Esta clase toma una pieza de texto y sustituye todas las variables dentro de ella. La definición predeterminada de una variable es $ {variableName}. El prefijo y el sufijo se pueden cambiar mediante constructores y establecer métodos.

Los valores de las variables normalmente se resuelven desde un mapa, pero también se pueden resolver a partir de las propiedades del sistema o mediante el suministro de un solucionador de variables personalizado.

Por ejemplo, si desea sustituir la variable de entorno del sistema en una cadena de plantilla, aquí está el código:

public class SysEnvSubstitutor { public static final String replace(final String source) { StrSubstitutor strSubstitutor = new StrSubstitutor( new StrLookup<Object>() { @Override public String lookup(final String key) { return System.getenv(key); } }); return strSubstitutor.replace(source); } }


Realmente no creo que necesites usar un motor de plantillas o algo así para esto. Puede usar el método String.format , así:

String template = "Hello %s Please find attached %s which is due on %s"; String message = String.format(template, name, invoiceNumber, dueDate);


solía

String template = "Hello %s Please find attached %s which is due on %s"; String message = String.format(template, name, invoiceNumber, dueDate);



String.format("Hello %s Please find attached %s which is due on %s", name, invoice, date)


System.out.println(MessageFormat.format("Hello {0}! You have {1} messages", "Join",10L));

Salida: ¡Hola, únete! Tienes 10 mensajes "