Подтвердить что ты не робот

Regex: что такое InCombiningDiacriticalMarks?

Следующий код очень хорошо известен для преобразования акцентированных символов в обычный текст:

Normalizer.normalize(text, Normalizer.Form.NFD).replaceAll("\\p{InCombiningDiacriticalMarks}+", "");

Я заменил свой метод "hand made" на этот, но мне нужно понять часть "regex" replaceAll

1) Что такое "InCombiningDiacriticalMarks"?
2) Где его документация? (и аналогий?)

Спасибо.

4b9b3361

Ответ 1

\p{InCombiningDiacriticalMarks} - свойство блока Unicode. В JDK7 вы сможете записать его с использованием двухзначной нотации \p{Block=CombiningDiacriticalMarks}, которая может быть более понятной для читателя. Документировано здесь, в UAX # 44: "База данных символов Юникода" .

Что это означает, что точка кода попадает в определенный диапазон, блок, который был выделен для использования для вещей под этим именем. Это плохой подход, потому что нет никакой гарантии, что кодовая точка в этом диапазоне является или не является какой-либо конкретной вещью, а не то, что код указывает вне этого блока, не имеет по существу одного и того же символа.

Например, в блоке \p{Latin_1_Supplement} есть латинские буквы, такие как é, U + 00E9. Однако есть вещи, которые не являются латинскими буквами. И, конечно, есть латинские буквы повсюду.

Блоки почти никогда не нужны.

В этом случае я подозреваю, что вы можете использовать свойство \p{Mn}, a.k.a. \p{Nonspacing_Mark}. Все кодовые точки в блоке Combining_Diacriticals относятся к этому типу. Также есть (как Unicode 6.0.0) 1087 Nonspacing_Marks, которые не находятся в этом блоке.

Это почти то же самое, что и проверка \p{Bidi_Class=Nonspacing_Mark}, но не совсем, потому что в эту группу также входят прилагаемые метки \p{Me}. Если вы хотите оба, вы можете сказать [\p{Mn}\p{Me}], если вы используете механизм регулярных выражений Java по умолчанию, поскольку он дает доступ только к свойству General_Category.

Вам нужно использовать JNI, чтобы получить в библиотеке регулярных выражений ICU С++ способ Google, чтобы получить доступ к чему-то вроде \p{BC=NSM}, потому что сейчас только ICU и Perl предоставляют доступ ко всем свойствам Unicode. Обычная библиотека Java regex поддерживает только несколько стандартных свойств Unicode. В JDK7, хотя будет поддержка свойства Unicode Script, что почти бесконечно предпочтительнее свойства Block. Таким образом, вы можете в JDK7 написать \p{Script=Latin} или \p{SC=Latin} или короткую вырезку \p{Latin}, чтобы получить любой символ из латинского script. Это приводит к обычному потреблению [\p{Latin}\p{Common}\p{Inherited}].

Имейте в виду, что это не удалит то, что вы можете назвать "акцентными" метками от всех персонажей! Их много не будет. Например, вы не можете преобразовать Đ в D или ø в o. Для этого вам нужно уменьшить кодовые точки до тех, которые соответствуют той же самой первичной силе сопоставления в таблице сортировки Unicode.

Другое место, где сбой \p{Mn} происходит, конечно, заключает в себе отметки типа \p{Me}, очевидно, но также есть символы \p{Diacritic}, которые не являются метками. К сожалению, вам нужна полная поддержка собственности для этого, что означает JNI либо для ICU, либо для Perl. Я боюсь, что у Java много проблем с поддержкой Unicode.

Ой, подождите, я вижу, что вы португальцы. У вас не должно быть никаких проблем, если вы имеете дело только с португальским текстом.

Тем не менее, вы действительно не хотите удалять акценты, я готов поспорить, но вы хотите, чтобы быть в состоянии соответствовать вещам "без акцента", верно? Если это так, то вы можете сделать это, используя класс ICU4J (ICU for Java). Если вы сравните с основной силой, знаки акцента не будут считаться. Я делаю это все время, потому что я часто обрабатываю испанский текст. У меня есть пример того, как это сделать для испанца, сидящего где-то здесь, если вам это нужно.

Ответ 2

Взял меня немного, но я выудил их всех:

Здесь regex, который должен включать все символы zalgo, в том числе и обходные в "нормальном" диапазоне.

([\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])

Надеюсь, это сэкономит вам некоторое время.