java - remove - Regex: ¿qué es InCombiningDiacriticalMarks?
remove special characters java (2)
Me tomó un tiempo, pero los saqué a todos:
Aquí está la expresión regular que debe incluir todos los caracteres zalgo, incluidos los omitidos en el rango "normal".
([/u0300–/u036F/u1AB0–/u1AFF/u1DC0–/u1DFF/u20D0–/u20FF/uFE20–/uFE2F/u0483-/u0486/u05C7/u0610-/u061A/u0656-/u065F/u0670/u06D6-/u06ED/u0711/u0730-/u073F/u0743-/u074A/u0F18-/u0F19/u0F35/u0F37/u0F72-/u0F73/u0F7A-/u0F81/u0F84/u0e00-/u0eff/uFC5E-/uFC62])
Espero que esto te ahorre algo de tiempo.
El siguiente código es muy conocido para convertir caracteres acentuados en texto sin formato:
Normalizer.normalize(text, Normalizer.Form.NFD).replaceAll("//p{InCombiningDiacriticalMarks}+", "");
Reemplacé mi método "hecho a mano" por este, pero necesito entender la parte "regex" de replaceAll
1) ¿Qué es "InCombiningDiacriticalMarks"?
2) ¿Dónde está la documentación de esto? (y similares?)
Gracias.
/p{InCombiningDiacriticalMarks}
es una propiedad de bloque Unicode. En JDK7, podrá escribirlo usando la notación de dos partes /p{Block=CombiningDiacriticalMarks}
, que puede ser más clara para el lector. Está documentado aquí en UAX # 44: "La base de datos de caracteres Unicode" .
Lo que significa es que el punto del código cae dentro de un rango particular, un bloque, que se ha asignado para usar para las cosas con ese nombre. Este es un mal enfoque, porque no hay garantía de que el punto de código en ese rango sea o no una cosa en particular, ni que los puntos de código fuera de ese bloque no sean esencialmente del mismo carácter.
Por ejemplo, hay letras latinas en el bloque /p{Latin_1_Supplement}
, como é, U + 00E9. Sin embargo, hay cosas que no son letras latinas allí también. Y, por supuesto, también hay letras latinas en todo el lugar.
Los bloques casi nunca son lo que quieres.
En este caso, sospecho que es posible que desee utilizar la propiedad /p{Mn}
, aka /p{Nonspacing_Mark}
. Todos los puntos de código en el bloque Combining_Diacriticals son de ese tipo. También hay (a partir de Unicode 6.0.0) 1087 Nonspacing_Marks que no están en ese bloque.
Eso es casi lo mismo que buscar /p{Bidi_Class=Nonspacing_Mark}
, pero no del todo, porque ese grupo también incluye las marcas adjuntas, /p{Me}
. Si quiere ambos, podría decir [/p{Mn}/p{Me}]
si está utilizando un motor de expresiones regulares Java predeterminado, ya que solo da acceso a la propiedad General_Category.
Tendría que usar JNI para acceder a la biblioteca de expresiones regex de ICU C ++ de la misma manera que Google para acceder a algo como /p{BC=NSM}
, porque ahora solo ICU y Perl dan acceso a todas las propiedades de Unicode. La biblioteca normal de expresiones regulares de Java admite solo un par de propiedades Unicode estándar. En JDK7, sin embargo , habrá soporte para la propiedad del script Unicode, que es casi infinitamente preferible a la propiedad Block. Por lo tanto, en JDK7 puede escribir /p{Script=Latin}
o /p{SC=Latin}
, o el atajo /p{Latin}
, para acceder a cualquier carácter del script latino. Esto lleva a lo que comúnmente se necesita [/p{Latin}/p{Common}/p{Inherited}]
.
Tenga en cuenta que eso no eliminará lo que podría pensar como marcas de "acento" de todos los personajes. Hay muchos que no harán esto por. Por ejemplo, no puede convertir Đ a D o ø a o de esa manera. Para eso, debe reducir los puntos de código a aquellos que coincidan con la misma intensidad de intercalación primaria en la tabla de intercalación Unicode.
Otro lugar donde la cosa /p{Mn}
falla es, por supuesto, delimitando marcas como /p{Me}
, obviamente, pero también hay /p{Diacritic}
caracteres que no son marcas. Lamentablemente, necesita un soporte de propiedad completo para eso, lo que significa JNI para ICU o Perl. Java tiene muchos problemas con el soporte Unicode, me temo.
Oh, espera, veo que eres portugués. No deberías tener ningún problema si solo tratas con texto en portugués.
Sin embargo, en realidad no quiere quitar los acentos, apuesto, sino que quiere ser capaz de hacer coincidir las cosas "sin acento en los acentos", ¿verdad? Si es así, puede hacerlo utilizando la clase de intercalador ICU4J (ICU para Java) . Si se compara en la fuerza principal, los acentos no contarán. Hago esto todo el tiempo porque a menudo trato el texto en español. Tengo un ejemplo de cómo hacer esto para español sentado aquí en algún lado si lo necesitas.