2010-01-12 9 views
24

Estoy buscando el mejor enfoque para encontrar y reemplazar cadenas en Java.¿La mejor forma de Java para encontrar y reemplazar cadenas?

Esta es una oración: "Mi nombre es Milán, la gente me conoce como Milan Vasic".

Quiero reemplazar la cadena Milan con Milan Vasic, pero en el lugar donde ya tengo Milan Vasic, eso no debería ser un caso.

después de buscar/reemplazar el resultado debería ser: "Mi nombre es Milan Vasic, la gente me conoce como Milan Vasic".

He intentado usar indexOf() y también la combinación Patrón/Matcher, pero ninguno de mis resultados parece elegante, ¿alguien tiene una solución elegante?

¡salud!

+1

¿Qué hay de Milan Bandic en tal caso? Vamos a tener un Milan Vasic y un Milan Bandic en la misma oración, por lo que el sistema ignorará al primer Milan, el segundo será Milan Vasic Bandic. :) –

+0

Heheeh ... Estaba usando mi nombre para este ejemplo :) – vaske

Respuesta

41

Bueno, se puede utilizar un regular expression para encontrar los casos en los que "Milan" no es seguida por "Vasic":

Milan(?! Vasic) 

y reemplazar que en el nombre completo:

String.replaceAll("Milan(?! Vasic)", "Milan Vasic") 

La parte (?!...) es una negative lookahead que asegura que cualquier coincidencia no sea seguida por la parte entre paréntesis. No consume ningún personaje en el partido en sí.

Alternativamente, puede simplemente insertar (bien, técnicamente reemplazando una coincidencia de ancho cero) el apellido después del nombre, a menos que ya esté seguido del apellido. Esto es similar, pero utiliza un positive lookbehind así:

(?<=Milan)(?! Vasic) 

Puede reemplazar esto simplemente " Vasic" (tenga en cuenta el espacio en el inicio de la cadena):

String.replaceAll("(?<=Milan)(?! Vasic)", " Vasic") 

Usted puede probar esas cosas here por ejemplo.

+1

Use java.lang.String.replaceAll (String, String) – helios

+0

Gracias; No lo busqué todavía :) – Joey

+0

Gracias, hombre, esto se ve muy elegante :) – vaske

5

Cuando no quiere poner su mano en la expresión regular (tal vez debería hacerlo), primero puede reemplazar toda la cadena "Milan Vasic" con "Milan".

Y que reemplazar todas las cadenas "Milan" con "Milan Vasic".

8

Una posibilidad, la reducción de la forma más larga antes de expandirse todo:

string.replaceAll("Milan Vasic", "Milan").replaceAll("Milan", "Milan Vasic") 

Otra manera, el tratamiento de Vasic como opcionales:

string.replaceAll("Milan(Vasic)?", "Milan Vasic") 

Otros han descrito soluciones basadas en lookahead o alternation.

+0

nice ... pero regex ya le permite indicar grupos que no capturan: (?! Milan) – helios

+0

Esa es una anticipación negativa. Los grupos que no capturaron serían '(?: ...)' – Joey

21

Otra opción:

"My name is Milan, people know me as Milan Vasic" 
    .replaceAll("Milan Vasic|Milan", "Milan Vasic")) 
+0

¡Gracias amigo, esto podría ser muy útil así como la primera respuesta! – vaske

+2

¡Una respuesta mucho más elegante! – lsiu

+1

No es elegante. Hace reemplazos inútiles. – ceving

2

Basta con incluir el JAR Apache Commons Lang y utilizar la clase org.apache.commons.lang.StringUtils. Notarás muchos métodos para reemplazar cadenas de manera segura y eficiente.

Puede ver la API de StringUtils en el sitio web vinculado anteriormente.

"No reinventar la rueda"

+0

Buena idea, y definitivamente estoy de acuerdo con eso si Java tuviera un sistema decente para utilizar el código escrito por otros (IE, PIP para Python,) entonces lo usaría. Pero no es así, así que soportamos la reinvención de la rueda porque es más fácil que usar la rueda que alguien más fabricó. – ArtOfWarfare

3

Prueba esto:

public static void main(String[] args) { 
    String str = "My name is Milan, people know me as Milan Vasic."; 

    Pattern p = Pattern.compile("(Milan)(?! Vasic)"); 
    Matcher m = p.matcher(str); 

    StringBuffer sb = new StringBuffer(); 

    while(m.find()) { 
     m.appendReplacement(sb, "Milan Vasic"); 
    } 

    m.appendTail(sb); 
    System.out.println(sb); 
} 
+0

Esta es una buena ilustración del caso general, en el que el reemplazo se puede calcular en tiempo de ejecución. –

1

puede utilizar el patrón de coincidencias, así, que sustituirá a todos en una sola toma.

Patrón keyPattern = Pattern.compile (clave); Matcher matcher = keyPattern.matcher (str); String nerSrting = matcher.replaceAll (value);

Cuestiones relacionadas