Проект ICU (который теперь также имеет библиотеку PHP ) содержит классы, необходимые для нормализации строк UTF-8, чтобы упростить сравнение значений при поиске.
Однако я пытаюсь понять, что это значит для приложений. Например, в каких случаях мне нужно «Каноническая эквивалентность» вместо «эквивалентности совместимости» или наоборот?
php
c
unicode
unicode-normalization
Xeoncross
источник
источник
(begin curved line) (char1) (char2) … (charN) (end curved line)
а не так:(curved line marker prefix) (char1) (curved line marker prefix) (char2) (curved line marker prefix) (char2)
. Другими словами, минимальный блок, который можно отрендерить?Ответы:
Все, что вы никогда не хотели знать о нормализации Unicode
Каноническая нормализация
Юникод включает несколько способов кодирования некоторых символов, в первую очередь символов с диакритическими знаками. Каноническая нормализация превращает кодовые точки в каноническую форму кодирования. Результирующие точки кода должны выглядеть идентичными исходным, за исключением каких-либо ошибок в шрифтах или механизме рендеринга.
Когда использовать
Поскольку результаты кажутся идентичными, всегда безопасно применять каноническую нормализацию к строке перед ее сохранением или отображением, если вы можете допустить, чтобы результат не был побитно идентичным входному.
Каноническая нормализация бывает двух видов: NFD и NFC. Эти две формы эквивалентны в том смысле, что можно конвертировать между этими двумя формами без потерь. Сравнение двух строк в NFC всегда будет давать тот же результат, что и их сравнение в NFD.
NFD
В NFD персонажи полностью раскрыты. Это более быстрая форма нормализации для вычисления, но приводит к большему количеству кодовых точек (т. Е. Использует больше места).
Если вы просто хотите сравнить две строки, которые еще не нормализованы, это предпочтительная форма нормализации, если вы не знаете, что вам нужна нормализация совместимости.
NFC
NFC рекомбинирует кодовые точки, когда это возможно, после запуска алгоритма NFD. Это занимает немного больше времени, но приводит к более коротким строкам.
Нормализация совместимости
Unicode также включает в себя множество символов, которые действительно не принадлежат, но использовались в устаревших наборах символов. Unicode добавил их, чтобы текст в этих наборах символов обрабатывался как Unicode, а затем конвертировался обратно без потерь.
Нормализация совместимости преобразует их в соответствующую последовательность «реальных» символов, а также выполняет каноническую нормализацию. Результаты нормализации совместимости могут не совпадать с оригиналами.
Символы, содержащие информацию о форматировании, заменяются на те, которых нет. Например, персонаж
⁹
преобразуется в9
. Другие не связаны с различиями в форматировании. Например, римская цифраⅨ
преобразуется в обычные буквыIX
.Очевидно, что после выполнения этого преобразования преобразование без потерь к исходному набору символов больше невозможно.
Когда использовать
Консорциум Unicode предлагает рассматривать нормализацию совместимости как
ToUpperCase
преобразование. Это то, что может быть полезно в некоторых обстоятельствах, но вы не должны применять его волей-неволей.Отличным вариантом использования будет поисковая система, поскольку вы, вероятно, захотите, чтобы поиск
9
соответствовал⁹
.Одна вещь, которую вам, вероятно, не следует делать, - это отображать пользователю результат применения нормализации совместимости.
NFKC / NFKD
Форма нормализации совместимости бывает двух видов: NFKD и NFKC. У них такие же отношения, как между NFD и C.
Любая строка в NFKC по своей сути также находится в NFC, и то же самое для NFKD и NFD. Таким образом
NFKD(x)=NFD(NFKC(x))
, иNFKC(x)=NFC(NFKD(x))
т. Д.Вывод
Если сомневаетесь, используйте каноническую нормализацию. Выберите NFC или NFD на основе применимого компромисса между пространством и скоростью или на основе того, что требуется для чего-то, с чем вы взаимодействуете.
источник
NFC(x)=Recompose(NFD(x))
.Некоторые символы, например буква с ударением (скажем,
é
), могут быть представлены двумя способами - одной кодовой точкойU+00E9
или простой буквой, за которой следует комбинированный знак ударенияU+0065 U+0301
. Обычная нормализация выберет один из них, чтобы всегда представлять его (единая кодовая точка для NFC, комбинированная форма для NFD).Для символов, которые могут быть представлены несколькими последовательностями базовых символов и комбинированных знаков (скажем, «s, точка внизу, точка вверху», а не точка вверху, затем точка внизу или использование базового символа, у которого уже есть одна из точек), NFD будет также выберите один из них (ниже идет первым, как это бывает)
Декомпозиции совместимости включают ряд символов, которые «на самом деле не должны» быть символами, но являются потому, что они использовались в устаревших кодировках. Обычная нормализация не объединит их (для сохранения целостности двустороннего обмена - это не проблема для комбинируемых форм, потому что никакая устаревшая кодировка [кроме нескольких вьетнамских кодировок] не использовала обе), но нормализация совместимости будет. Подумайте о знаке килограмма «kg», который появляется в некоторых восточноазиатских кодировках (или катакане и алфавите половинной / полной ширины), или о лигатуре «fi» в MacRoman.
См. Http://unicode.org/reports/tr15/ для получения дополнительной информации.
источник
Нормальные формы (Unicode, а не базы данных) имеют дело в первую очередь (исключительно?) С символами, имеющими диакритические знаки. Unicode предоставляет некоторые символы со «встроенными» диакритическими знаками, например U + 00C0, «латинская заглавная буква A с могилой». Один и тот же символ может быть создан из «Latin Capital A» (U + 0041) с «Combining Grave Accent» (U + 0300). Это означает, что даже если две последовательности производят один и тот же результирующий символ, побайтно сравнение покажет, что они совершенно разные.
Нормализация - это попытка справиться с этим. Нормализация гарантирует (или, по крайней мере, пытается), что все символы закодированы одинаково - либо все с использованием отдельного комбинированного диакритического знака, где это необходимо, либо с использованием единой кодовой точки, где это возможно. С точки зрения сравнения, на самом деле не имеет большого значения, что вы выберете - практически любая нормализованная строка будет правильно сравниваться с другой нормализованной строкой.
В этом случае «совместимость» означает совместимость с кодом, который предполагает, что одна кодовая точка равна одному символу. Если у вас есть такой код, вы, вероятно, захотите использовать обычную форму совместимости. Хотя я никогда не видел, чтобы это прямо говорилось, названия нормальных форм подразумевают, что консорциум Unicode считает предпочтительным использовать отдельные комбинированные диакритические знаки. Это требует большего интеллекта для подсчета фактических символов в строке (а также таких вещей, как разумное прерывание строки), но это более универсально.
Если вы в полной мере используете ICU, скорее всего, вы захотите использовать каноническую нормальную форму. Если вы пытаетесь написать код самостоятельно, который (например) предполагает, что кодовая точка равна символу, то вам, вероятно, понадобится нормальная форма совместимости, которая делает это как можно чаще.
источник
"o\x{332}\x{303}\x{304}"
, а NFC есть"\x{22D}\x{332}"
. Для второго NFD есть"o\x{332}\x{304}\x{303}"
и NFC есть"\x{14D}\x{332}\x{303}"
. Однако существует множество неканонических возможностей, которые канонически им эквивалентны. Нормализация позволяет бинарное сравнение канонически эквивалентных графем.Если две строки Unicode канонически эквивалентны, строки действительно одинаковы, только с использованием разных последовательностей Unicode. Например, Ä можно представить с помощью символа Ä или комбинации A и ◌̈.
Если строки эквивалентны только совместимости, строки не обязательно должны быть одинаковыми, но они могут быть одинаковыми в некоторых контекстах. Например, ff можно считать тем же, что и ff.
Итак, если вы сравниваете строки, вы должны использовать каноническую эквивалентность, потому что эквивалентность совместимости не является реальной эквивалентностью.
Но если вы хотите отсортировать набор строк, может иметь смысл использовать эквивалент совместимости, поскольку они почти идентичны.
источник
На самом деле это довольно просто. UTF-8 фактически имеет несколько различных представлений одного и того же «символа». (Я использую символы в кавычках, поскольку побайтно они разные, но практически одинаковы). Пример приведен в связанном документе.
Символ «Ç» можно представить как последовательность байтов 0xc387. Но он также может быть представлен
C
(0x43), за которым следует последовательность байтов 0xcca7. Таким образом, вы можете сказать, что 0xc387 и 0x43cca7 - это один и тот же символ. Причина, по которой это работает, заключается в том, что 0xcca7 - это знак объединения; то есть он берет символ перед ним (C
здесь) и изменяет его.Теперь, что касается разницы между канонической эквивалентностью и эквивалентностью совместимости, нам нужно взглянуть на символы в целом.
Есть 2 типа символов: те, которые передают значение через значение , и те, которые принимают другой символ и изменяют его. 9 - значимый персонаж. Суперсценарий ⁹ принимает это значение и изменяет его путем представления. Таким образом, канонически они имеют разные значения, но все же представляют собой базовый символ.
Каноническая эквивалентность - это когда последовательность байтов отображает один и тот же символ с одинаковым значением. Эквивалентность совместимости - это когда последовательность байтов отображает другой символ с тем же базовым значением (даже если он может быть изменен). 9 и ⁹ эквивалентны по совместимости, так как оба они означают «9», но канонически не эквивалентны, так как имеют разные представления.
источник
Что вам больше подходит - каноническая эквивалентность или эквивалентность совместимости, зависит от вашего приложения. ASCII-образное представление о сравнении строк примерно соответствует канонической эквивалентности, но Unicode представляет множество языков. Я не думаю, что можно безопасно предполагать, что Unicode кодирует все языки таким образом, чтобы вы могли обращаться с ними так же, как с западноевропейским ASCII.
На рисунках 1 и 2 представлены хорошие примеры двух типов эквивалентности. С точки зрения эквивалентности совместимости, похоже, что одно и то же число в форме суб- и надскрипта будет равнозначно. Но я не уверен, что это решит ту же проблему, что и курсивная арабская форма или повернутые символы.
Жесткая правда обработки текста Unicode заключается в том, что вы должны глубоко подумать о требованиях вашего приложения к обработке текста, а затем решить их, как можно лучше, с помощью доступных инструментов. Это не касается напрямую вашего вопроса, но для более подробного ответа потребуются лингвистические эксперты для каждого из языков, которые вы ожидаете поддерживать.
источник
Проблема сравнения строк : две строки с содержимым, эквивалентным для большинства приложений, могут содержать разные последовательности символов.
См . Каноническую эквивалентность Unicode : если алгоритм сравнения простой (или должен быть быстрым), эквивалентность Unicode не выполняется. Эта проблема возникает, например, при каноническом сравнении XML, см. Http://www.w3.org/TR/xml-c14n
Чтобы избежать этой проблемы ... Какой стандарт использовать? "расширенный UTF8" или "компактный UTF8"?
Используйте «ç» или «c + ◌̧.»?
W3C и другие (например, имена файлов ) предлагают использовать «составленные как канонические» (не забывайте о «самых компактных» более коротких строках) ... Итак,
Стандарт - C ! сомневаетесь в использовании NFC
Для совместимости и для выбора «соглашение по конфигурации» рекомендуется использовать NFC для «канонизации» внешних строк. Например, чтобы сохранить канонический XML, сохраните его в «FORM_C». Рабочая группа W3C CSV в Интернете также рекомендует NFC (раздел 7.2).
PS: de "FORM_C" - это форма по умолчанию в большинстве библиотек. Ex. в PHP normalizer.isnormalized () .
Термин « форма композиции » (
FORM_C
) используется как для того, чтобы сказать, что «строка находится в C-канонической форме» (результат преобразования NFC), так и для того, чтобы сказать, что используется алгоритм преобразования ... См. Http: //www.macchiato.com/unicode/nfc-faqПримечание: для проверки нормализации маленьких строк (чистый UTF-8 или ссылки на XML-сущности) вы можете использовать этот онлайн-конвертер тестирования / нормализации .
источник