O código a seguir é muito conhecido por converter caracteres acentuados em texto simples:
Normalizer.normalize(text, Normalizer.Form.NFD).replaceAll("\\p{InCombiningDiacriticalMarks}+", "");
Substituí meu método "feito à mão" por este, mas preciso entender a parte "regex" do replaceAll
1) O que é "InCombiningDiacriticalMarks"?
2) Onde está a documentação disso? (e similares?)
Obrigado.
Respostas:
\p{InCombiningDiacriticalMarks}
é uma propriedade de bloco Unicode. No JDK7, você poderá escrevê-lo usando a notação de duas partes\p{Block=CombiningDiacriticalMarks}
, o que pode ser mais claro para o leitor. Está documentado aqui em UAX # 44: “The Unicode Character Database” .O que isso significa é que o ponto de código está dentro de um intervalo específico, um bloco, que foi alocado para uso para as coisas com aquele nome. Esta é uma abordagem ruim, porque não há garantia de que o ponto de código nesse intervalo seja ou não uma coisa particular, nem que os pontos de código fora desse bloco não sejam essencialmente do mesmo caractere.
Por exemplo, existem letras latinas no
\p{Latin_1_Supplement}
bloco, como é, U + 00E9. No entanto, há coisas que não são letras latinas também. E, claro, também há letras latinas por todo o lugar.Os blocos quase nunca são o que você deseja.
Nesse caso, suspeito que você queira usar a propriedade
\p{Mn}
, também conhecida como\p{Nonspacing_Mark}
. Todos os pontos de código no bloco Combining_Diacriticals são desse tipo. Existem também (a partir do Unicode 6.0.0) 1087 Nonspacing_Marks que não estão naquele bloco.Isso é quase o mesmo que verificar
\p{Bidi_Class=Nonspacing_Mark}
, mas não exatamente, porque esse grupo também inclui as marcas delimitadoras\p{Me}
,. Se você quiser os dois, pode dizer[\p{Mn}\p{Me}]
se está usando um mecanismo regex Java padrão, já que ele só dá acesso à propriedade General_Category.Você teria que usar JNI para chegar à biblioteca regex ICU C ++ da maneira que o Google faz para acessar algo como
\p{BC=NSM}
, porque agora apenas ICU e Perl dão acesso a todas as propriedades Unicode. A biblioteca Java regex normal suporta apenas algumas propriedades Unicode padrão. No entanto, no JDK7 haverá suporte para a propriedade Unicode Script, que é quase infinitamente preferível à propriedade Block. Assim, você pode escrever em JDK7\p{Script=Latin}
ou\p{SC=Latin}
, ou o atalho\p{Latin}
, para obter qualquer caractere do script latino. Isso leva ao muito comumente necessário[\p{Latin}\p{Common}\p{Inherited}]
.Esteja ciente de que isso não removerá o que você pode pensar como marcas de “acento” de todos os personagens! Há muitos pelos quais ele não fará isso. Por exemplo, você não pode converter Đ em D ou ø em o dessa maneira. Para isso, você precisa reduzir os pontos de código para aqueles que correspondem à mesma intensidade de agrupamento primário na Tabela de agrupamento Unicode.
Outro ponto onde a
\p{Mn}
coisa falha é, claro, marcas encerradas como\p{Me}
, obviamente, mas também há\p{Diacritic}
caracteres que não são marcas. Infelizmente, você precisa de suporte total de propriedade para isso, o que significa JNI para ICU ou Perl. Java tem muitos problemas com o suporte a Unicode, infelizmente.Oh espere, vejo que você é português. Você não deverá ter problemas se estiver lidando apenas com texto em português.
No entanto, você não quer realmente remover os acentos, aposto, mas sim ser capaz de combinar as coisas “de maneira insensível”, certo? Em caso afirmativo, você pode fazer isso usando a classe de intercalador ICU4J (ICU para Java) . Se você comparar na intensidade primária, os acentos não contarão. Eu faço isso o tempo todo porque frequentemente processo textos em espanhol. Eu tenho um exemplo de como fazer isso para o espanhol sentado aqui em algum lugar, se você precisar.
fonte
Demorei um pouco, mas pesquei todos eles:
Aqui está o regex que deve incluir todos os caracteres zalgo, incluindo aqueles ignorados no intervalo 'normal'.
Espero que isso economize algum tempo.
fonte