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?
- ¿Cómo puedo crear una expresión regular para esto en android?
- Fuerza de cierre en la expresión regular!
- Regex opcional de límites de palabras de Android
- Permitir sólo charcters seleccionados basados en regex en un EditText
- Validar cadena con regex en android
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.
- Cómo validar String usando expresión regular en java
- ¿Cuál sería una simple expresión regular para la comprobación de contraseña durante la suscripción?
- Cómo reemplazar una cadena si no está contenida entre '<' y '>'
- Cómo encontrar elementos por subcadena de ID usando la sintaxis del selector Jsoup?
- ¿Cómo puedo eliminar la cadena de caracteres dinámicos de una cadena?
- Android / Java Regex para eliminar ceros adicionales de sub-cadenas
- Cómo utilizar SpannableString con Regex en android?
- ¿Cómo lograr límite de palabras en Sqlite Android?
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 mostrar el estado de la conexión bluetooth en android
- Mover EditText en NestedScrollView cuando aparece el teclado virtual