Обнаружение высоких суррогатов в строке с помощью регулярных выражений - PullRequest
3 голосов
/ 01 августа 2011

Я хочу проверить, содержит ли строка какие-либо высокие суррогаты.В Java я использовал бы Character.isHighSurrogate (c), и это работает.

В регулярном выражении (с использованием реализации, предоставляемой Android 2.3.3 SDK), я ожидал, что это сработает:

[\uD800-\uDBFF]

но это не так.

Я использую символ: ? (кодовая точка: 177700), чтобы проверить это (работает в моей проверке Java, но не проверке регулярных выражений).

Есть идеи?

Ответы [ 2 ]

6 голосов
/ 01 августа 2011

Движок регулярных выражений смотрит на код точек , не на код единиц . У него нет выбора, потому что это фундаментальныйтребование UTS # 18 Уровень 1 Поддержка Unicode :

Уровень 1: Базовая поддержка Unicode.На этом уровне механизм регулярных выражений обеспечивает поддержку символов Юникода в качестве базовых логических единиц.(Это не зависит от фактической сериализации Unicode как UTF-8, UTF-16BE, UTF-16LE, UTF-32BE или UTF-32LE.) Это минимальный уровень для полезной поддержки Unicode.Он не учитывает ожидания конечных пользователей в отношении поддержки символов, но удовлетворяет большинству требований программиста низкого уровня.Результаты сопоставления регулярных выражений на этом уровне не зависят от страны или языка.На этом уровне пользователю обработчика регулярных выражений потребуется написать более сложные регулярные выражения, чтобы выполнить полную обработку Unicode.

И поэтому это верно как в обычном обработчике регулярных выражений JDK, так и вМеханизм регулярных выражений Android, который JNI включает в библиотеку регулярных выражений ICU , обеспечивает намного лучшую поддержку Unicode, чем JDK.Помимо прочего, ICU отвечает всем требованиям уровня 1, а также некоторым требованиям уровня 2, таким как полные свойства (готовящийся к выпуску 2.7), графем и более привлекательные границы.Вы не доберетесь до уровня 1 до JDK7, и даже там ему не хватает остальных.С Unicode очень трудно работать без поддержки графем и невозможно без поддержки кодовых точек.

Иногда вы можете найти такие вещи, чтобы найти изолированные суррогаты или обратные, но они не должны встречаться в данныхдействителен для обмена.

В общем, вы хотите держаться как можно дальше от любого интерфейса кодовой единицы, и использовать только те API, которые поддерживают интерфейс кодовой точки.Единицы кода - это проклятие.

Кроме того, держитесь подальше от препроцессора Java.Таким образом, вы не получите никакой радости от своих регулярных выражений.Движок регулярных выражений ICU поддерживает как \x{ᴄᴏᴅᴇ ᴘᴏɪɴᴛ}, так и \N{ᴄʜᴀʀɴᴀᴍᴇ}, поэтому вы должны их использовать.

Почему вы все время возитесь с злобно-мерзким кодом единиц ?Они нарушают абстракцию кодовой точки.

0 голосов
/ 01 августа 2011

Глядя на документацию для Pattern , есть пример для сопоставления греческих символов, ссылающихся на Character.UnicodeBlock

Классы для блоков и категорий Unicode

\ p {InGreek} Символ в греческом блоке (простой блок )

Доступные константы в этом классе содержат LOW_SURROGATES , предполагая, что выражение regex на android совместимо с jdk, я попробовал следующий код:

String test = new String(Character.toChars(177700));

System.out.println(Pattern.compile("\\p{InLowSurrogates}").matcher(test).find());
System.out.println(Pattern.compile("\\p{InLOW_SURROGATES}").matcher(test).find());

Который печатает "true" два раза, что означает, что оба стиля именования работают, и он правильно обнаруживает низкие суррогаты.

Как ни странно, один и тот же код не работает для старших суррогатов, т. Е. Следующие строки выдают false:

System.out.println(Pattern.compile("\\p{InHighSurrogates}").matcher(test).find());
System.out.println(Pattern.compile("\\p{InHIGH_SURROGATES}").matcher(test).find());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...