Regex no funciona en Android pero funciona bien en Java

Tengo el siguiente código:

String compact = Pattern.compile(" *(\\{) *| *(\\}) *").matcher(" { { } } ") .replaceAll("$1$2"); 

En Java, compact contiene {{}} – que es lo que quiero – pero en Android, estoy recibiendo {null{nullnull}null} que me está volviendo loco. ¿Estoy haciendo algo mal?

La siguiente línea produce el mismo resultado en Android:

 String compact = " { { } } ".replaceAll(" *(\\{) *| *(\\}) *", "$1$2") 

Aquí está una versión en línea de Java para cualquier persona que quiera jugar con ella.

Si ayuda, estoy compilando contra Android SDK 23 con jdk1.7.0_79 en Mac en Android Studio.

Actualización: El uso de "\\s*(\\{)\\s*|\\s*(\\})\\s*" tiene el mismo efecto.

No puedo decirte por qué se comporta así en Java, pero puedo decirte por qué se comporta así en Android. Puedo dar algunas pistas sobre Java sin embargo.

Cuando Matcher#replaceAll(String) un Matcher#replaceAll(String) , la clase comprueba si hay un find() , y si lo tiene, reemplaza lo que se emparejó en la entrada con esa String reemplazo que proporcionaste.

Hasta aquí todo bien.

Sin embargo, cuando el reemplazo es realmente una representación de un grupo, se toma otra ruta. La clase intenta encontrar lo que corresponde a ese grupo (vea Matcher#appendEvaluated(StringBuffer, String) ) y append(String) al StringBuffer interno que se usa internamente.

Lo hace llamando explícitamente al método group(int) . El comportamiento de este método tanto en Java como en Android es que devolverá null si, cuando hay una coincidencia, no hay una que corresponda al grupo dado. Nota: lanza la excepción cuando no hay un fósforo en absoluto y no sólo cuando no puede encontrar uno que corresponde al grupo. Como el group(int) sin find() , por ejemplo.

Al final, StringBuffer emite la String "null" (literalmente la palabra "null") cuando se agrega un objeto null . Por lo tanto, para cada grupo que usted pide que no esté allí, cuando hay un fósforo, agregará la palabra "null" a ella.

Los algoritmos utilizados en Java son muy diferentes y tienen una salida diferente en ese caso de replaceAll .

Sin probar demasiado o la fijación de ineficiencias (lo siento, sólo navegar SO a las 3 de la mañana en diciembre no me ayuda a pensar en línea recta), creo que podría lograr, en Android, los mismos resultados que obtendría utilizando lo que estaba utilizando en Java, haciendo esto en lugar de replaceAll :

 String input = " { { } } "; Matcher matcher = Pattern.compile(" *(\\{) *| *(\\}) *").matcher(input); while (matcher.find()) { String a = matcher.group(1); // $1 String b = matcher.group(2); // $2 String replacement = null; if (a != null && b != null) { replacement = a + b; } else if (a != null) { replacement = a; } else if (b != null) { replacement = b; } if (replacement != null) { input = input.replace(matcher.group(), replacement); } } 

Si no lo hace, por favor hágamelo saber. Sólo hice algunas pruebas de crudo (es 3 am después de todo).

  • Cómo colorear texto utilizando Regex en android
  • Regex <img> Análisis de etiquetas con src, width, height
  • División de la cadena con RegEx en Android
  • java.util.regex.PatternSyntaxException: Error de sintaxis en patrón regex cerca de índice
  • Formato de registro de registro de Android c2dm
  • Java.util.regex.PatternSyntaxException en Android
  • Problema que coincide con el patrón regex en Android
  • Android, String.split (String regex) no divide toda la cadena
  • ReplaceAll no reemplaza string
  • Buscar una subcadena entre ciertos caracteres en un índice desconocido
  • ¿Cómo usar los marcadores de principio y fin en regex para Java String?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.