Regex: что такое InCombiningDiacriticalMarks?
Следующий код хорошо известен для преобразования акцентированных символов в обычный текст:
Normalizer.normalize(text, Normalizer.Form.NFD).replaceAll("\\p{InCombiningDiacriticalMarks}+", "");
Я заменил свой "ручной" метод на этот, но мне нужно понять "регулярное выражение" части replaceAll
1) Что такое "InCombiningDiacriticalMarks"?
2) Где документация на это? (а похожие?)
Благодарю.
2 ответа
\p{InCombiningDiacriticalMarks}
является свойством блока Unicode. В JDK7 вы сможете написать его, используя запись из двух частей \p{Block=CombiningDiacriticalMarks}
, что может быть понятнее читателю. Это задокументировано здесь, в UAX#44: "База данных символов Unicode".
Это означает, что кодовая точка попадает в определенный диапазон, блок, который был выделен для использования с вещами под этим именем. Это плохой подход, потому что нет гарантии, что кодовая точка в этом диапазоне является или не является какой-то конкретной вещью, а также что кодовые точки вне этого блока не имеют по существу один и тот же символ.
Например, есть латинские буквы в \p{Latin_1_Supplement}
блок, как у, U+00E9. Однако есть вещи, которые не являются латинскими буквами. И, конечно же, повсюду есть латинские буквы.
Блоки почти никогда не то, что вы хотите.
В этом случае я подозреваю, что вы можете использовать собственность \p{Mn}
ака \p{Nonspacing_Mark}
, Все кодовые точки в блоке Combining_Diacriticals являются такими. Также есть (по состоянию на Unicode 6.0.0) 1087 Nonspacing_Marks, которые не находятся в этом блоке.
Это почти так же, как проверка на \p{Bidi_Class=Nonspacing_Mark}
, но не совсем, потому что эта группа также включает в себя знаки, \p{Me}
, Если вы хотите оба, вы могли бы сказать, [\p{Mn}\p{Me}]
если вы используете стандартное ядро Java regex, так как оно дает доступ только к свойству General_Category.
Вы должны использовать JNI, чтобы получить доступ к библиотеке регулярных выражений ICU C++, как это делает Google, чтобы получить доступ к чему-то вроде \p{BC=NSM}
потому что сейчас только ICU и Perl предоставляют доступ ко всем свойствам Unicode. Обычная библиотека регулярных выражений Java поддерживает только пару стандартных свойств Unicode. В JDK7 будет поддерживаться свойство Unicode Script, которое почти бесконечно предпочтительнее свойства Block. Таким образом вы можете в JDK7 написать \p{Script=Latin}
или же \p{SC=Latin}
или короткий путь \p{Latin}
, чтобы получить любой символ из латинского алфавита. Это приводит к очень часто [\p{Latin}\p{Common}\p{Inherited}]
,
Имейте в виду, что это не удалит то, что вы можете считать "акцентными" отметками у всех персонажей! Есть много, что он не будет делать это для. Например, вы не можете конвертировать Đ в D или ø в o таким образом. Для этого вам нужно уменьшить количество кодовых точек до тех, которые соответствуют той же силе первичного сопоставления в таблице сопоставления Unicode.
Другое место, где \p{Mn}
вещь терпит неудачу, конечно, включает в себя такие знаки, как \p{Me}
, очевидно, но есть \p{Diacritic}
символы, которые не являются отметками. К сожалению, вам нужна полная поддержка свойств для этого, что означает JNI для ICU или Perl. Боюсь, у Java много проблем с поддержкой Unicode.
Ой, подождите, я вижу, вы португальский. У вас не должно быть никаких проблем, если вы имеете дело только с португальским текстом.
Тем не менее, я уверен, что вы не хотите удалять акценты, а хотите, чтобы вы могли сопоставлять вещи "без акцента", верно? Если это так, то вы можете сделать это, используя класс коллатера ICU4J (ICU для Java). Если вы сравните в первичной силе, знаки акцента не будут учитываться. Я делаю это все время, потому что я часто обрабатываю текст на испанском языке. У меня есть пример того, как сделать это для испанцев, сидящих где-то здесь, если вам это нужно.
Это заняло у меня некоторое время, но я выловил их всех:
Вот регулярное выражение, которое должно включать все символы 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])
Надеюсь, это сэкономит вам время.