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).

  • Utilizar un signo de interrogación como String en android
  • Android reemplazar con regex
  • Cómo encontrar elementos por subcadena de ID usando la sintaxis del selector Jsoup?
  • Cómo colorear texto utilizando Regex en android
  • Regex <img> Análisis de etiquetas con src, width, height
  • Android / Java: comprueba si url es url válida de youtube
  • Referencia a grupos coincidentes anteriores dentro de un regex
  • ReplaceAll no reemplaza string
  • Caracteres especiales de Android Sqlite
  • Java.util.regex.PatternSyntaxException en Android
  • Editar texto aceptar sólo números no números decimales en android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.