正規化されたUTF-8とは何ですか?


129

ICUプロジェクト(今も持っているPHPライブラリは)検索するときに、それが簡単に値を比較するために行うために、ヘルプノーマライズUTF-8文字列に必要なクラスが含まれています。

ただし、これがアプリケーションにとって何を意味するのを理解しようとしてます。たとえば、「互換性の同等性」ではなく「正規の同等性」が必要な場合、またはその逆はどのような場合ですか。


230
w͢͢͝h͡o̸͢͢͡k̵͟n̴͘ǫw̸̛s̀́͘w͘͢ḩ̵a҉̡͢t ̧̕h́o̵r͏̵rors̶̡͡͠lį̶e̶͟͟͝in͢͏t̕h̷̡͟e͟͟d̛a͜r̕͡k̢̨͡h̴e͏a̷̢̡rt́͏̴̷͠ò̵̶f̸u̧͘ní̛͜c͢͏o̷͏d̸͢e̡͝?͞–
ObscureRobot

@ObscureRobotこれらの追加のシンボルが状態を持つことができるかどうかを本当に知りたい
eonil

1
@Eonil-ユニコードのコンテキストでどのような状態が意味するのかわかりません。
ObscureRobot 2013年

@ObscureRobotたとえば、次のようなコードポイント:これ(begin curved line) (char1) (char2) … (charN) (end curved line)ではなく:(curved line marker prefix) (char1) (curved line marker prefix) (char2) (curved line marker prefix) (char2)。つまり、レンダリングできる最小単位は?
eonil 2013年

2
それ自体は良い質問のように思えます。
ObscureRobot 2013年

回答:


181

Unicode正規化について知りたくないことすべて

正規化

Unicodeには、いくつかの文字、特にアクセント付き文字をエンコードする複数の方法が含まれています。正規正規化は、コードポイントを正規エンコード形式に変更します。結果のコードポイントは、フォントやレンダリングエンジンのバグを除いて、元のコードポイントと同じように見えるはずです。

いつ使用するか

結果は同一に見えるため、結果が入力とビットごとに同一でないことを許容できる限り、文字列を保存または表示する前に正規正規化を適用しても常に安全です。

正規化には、NFDとNFCの2つの形式があります。この2つは、これら2つの形式間で損失なく変換できるという意味で同等です。NFCで2つの文字列を比較すると、常にNFDで比較した場合と同じ結果になります。

NFD

NFDのキャラクターは完全に拡張されています。これは、計算するのに高速な正規化形式ですが、結果としてコードポイントが多くなります(つまり、より多くのスペースを使用します)。

まだ正規化されていない2つの文字列を比較するだけの場合は、互換性の正規化が必要であることがわかっている場合を除き、これが推奨される正規化形式です。

NFC

NFCは、NFDアルゴリズムの実行後、可能な場合にコードポイントを再結合します。これには少し時間がかかりますが、文字列は短くなります。

互換性の正規化

Unicodeには、実際には属さないが、従来の文字セットで使用されていた多くの文字も含まれています。Unicodeはこれらを追加して、これらの文字セットのテキストをUnicodeとして処理し、損失なしで元に戻すことができるようにしました。

互換性の正規化は、これらを「実際の」文字の対応するシーケンスに変換し、正規の正規化も実行します。互換性の正規化の結果は、オリジナルと同じに見えない場合があります。

フォーマット情報を含む文字は、含まない文字に置き換えられます。たとえば、文字はに変換され9ます。他のものはフォーマットの違いを含みません。たとえば、ローマ数字の文字は通常の文字に変換されますIXます。

明らかに、この変換が実行されると、元の文字セットに無損失で変換することはできなくなります。

いつ使うか

Unicodeコンソーシアムは、ToUpperCase変換のような互換性の正規化について考えることを提案しています。状況によっては便利な場合もありますが、そのまま適用してはなりません。

9一致するものを検索したいので、優れたユースケースは検索エンジンです。

おそらくすべきでないことの1つは、互換性の正規化をユーザーに適用した結果を表示することです。

NFKC / NFKD

互換性正規化形式には、NFKDとNFKCの2つの形式があります。NFDとCの間の関係と同じです。

NFKCの文字列は、本質的にNFCにもあり、NFKDとNFDでも同じです。このようにNFKD(x)=NFD(NFKC(x))、そしてNFKC(x)=NFC(NFKD(x))、など

結論

疑問がある場合は、正規化を行ってください。適用可能なスペース/速度のトレードオフに基づいて、または相互運用しているものに必要なものに基づいて、NFCまたはNFDを選択します。


42
略語の意味を覚えておくためのクイックリファレンス:NF = 正規化された形式 D = 分解(圧縮解除)C = 構成(圧縮) K = 互換性(「C」が採用されたため)。
Mike Spross、2011年

12
常に最初の入力としてすべての文字列をNFDに、最後にNFCすべての文字列を出力する必要があります。これはよく知られています。
tchrist

3
@tchrist:変更が加えられていないときに、出力を入力とバイトごとに同一にするまれな場合を除いて、これは一般的に良いアドバイスです。メモリ内のNFCまたはディスク上のNFDが必要な場合もありますが、それらは規則ではなく例外です。
Kevin Cathcart、2011年

@Kevin:はい、NFDインとNFCアウトはシングルトンを破壊します。誰もがそれらを気にかけているかどうかはわかりませんが、おそらくそうでしょう。
tchrist

2
あなたはそれを考えるかもしれませんが、「Unicode文字列を特定のUnicode正規化形式に変換するための最初のステップは、文字列を完全に分解することです。」したがって、NFCを実行しているwehenでも、Q-Caronは最初にQ + Caronになり、再構成できませんでした。これは、安定性ルールが新しいコンポジションマッピングの追加を禁止しているためです。NFCは事実上として定義されNFC(x)=Recompose(NFD(x))ます。
Kevin Cathcart 2013

40

一部の文字、たとえばアクセント付きの文字(たとえば、é)は、2つの方法で表現できます-単一のコードポイント、U+00E9またはプレーンな文字の後にアクセント記号を組み合わせたものU+0065 U+0301です。通常の正規化では、これらの1つを選択して常にそれを表します(NFCの単一のコードポイント、NFDの結合形式)。

ベース文字と結合マークの複数のシーケンスで表すことができる文字(たとえば、「s、下にドット、上のドット」と、上にドットを下にしてドットを下に置く、またはすでにドットの1つを含むベース文字を使用する)の場合、NFDはまた、これらの1つを選択します(以下のように、最初に行ってください)

互換性の分解には、「実際にはそうではないはずの」文字である多数の文字が含まれますが、これは、それらがレガシーエンコーディングで使用されたためです。通常の正規化ではこれらは統一されません(往復の整合性を維持するために、レガシーエンコーディング(少数のベトナムエンコーディングを除く)が両方を使用していないため、これは結合フォームの問題ではありません)ですが、互換性の正規化はそうです。一部の東アジアのエンコーディング(または半角/全角カタカナとアルファベット)に表示される「kg」キログラム記号、またはMacRomanの「fi」合字のように考えてください。

詳細については、http://unicode.org/reports/tr15/を参照してください。


1
これが正解です。一部のレガシー文字セットで作成されたテキストで正規正規化のみを使用すると、結果を失うことなくその文字セットに変換し直すことができます。互換性分解を使用すると、互換性文字はなくなりますが、元の文字セットに変換して失うことはできなくなります。
Kevin Cathcart、2011年

13

(データベースではなくUnicodeの)通常の形式は、主に(排他的に?)、発音区別符号付きの文字を扱います。Unicodeは、U + 00C0、「ラテンキャピタルA、墓付き」など、一部の文字に「組み込み」の発音区別符号を提供します。「ラテン大文字A」(U + 0041)から「結合アクセント(U + 0300)」を使用して同じ文字を作成できます。これは、2つのシーケンスがバイトごとに同じ文字を生成したとしても、比較すると、それらは完全に異なるものとして表示されます。

正規化はそれに対処する試みです。正規化により、すべての文字が同じ方法でエンコードされることが保証されます(または少なくとも試行されます)。すべて、必要な場合はすべて別の結合ダイアクリティカルマークを使用するか、可能な場合はすべて単一のコードポイントを使用します。比較の観点から見ると、どれを選択するかは重要ではありません。ほとんどの正規化文字列は、別の正規化文字列と適切に比較されます。

この場合、「互換性」とは、1つのコードポイントが1つの文字に等しいと想定するコードとの互換性を意味します。そのようなコードがある場合、互換性のある通常の形式を使用したいと思うでしょう。私はそれが直接述べられているのを見たことはありませんが、標準形式の名前は、Unicodeコンソーシアムが個別の発音区別記号を組み合わせて使用​​することが望ましいと見なしていることを意味します。これは、文字列内の実際の文字をカウントするために(さらに、文字列をインテリジェントに分割するなど)より多くのインテリジェンスを必要としますが、より汎用性があります。

ICUを最大限に活用している場合は、正規の正規形を使用する可能性があります。(たとえば)コードポイントが文字に等しいと想定して独自にコードを記述しようとしている場合、おそらくそれを可能な限り頻繁に行う互換性の正規形が必要です。


つまり、これが書記素関数の出番です。文字はASCIIよりもバイト数が多いだけでなく、複数のシーケンスが1つの文字になり得ますか?(MB文字列関数とは異なります。)
Xeoncross

4
いいえ、「1つのコードポイントは1つの文字」はおおよそNFCに対応します(結合マークのあるものはNFDであり、どちらも「互換性」ではありません)-互換性の正規化NFKC / NFKDは別の問題です。たとえばギリシャ語のmuと 'micro'に別の文字があったレガシーエンコーディングの互換性(またはその欠如)(「互換性」バージョンはLatin 1ブロックにあるバージョンであるため、これは楽しいものです)
Random832

@ Random832:おっと、そうですね。過去1〜2年間作業をしていなかったときは、記憶から戻るよりも、もっとよく知っているべきです。
ジェリー棺

@ Random832それは本当ではない。あなたの「だいたい」はあまりにも外にあります。2つの書記素、ō̲̃とConsiderを考えます。それぞれを書く方法はたくさんありますが、それぞれ1つはNFCと1つのNFDですが、他の方法も存在します。コードポイントが1つだけであるということはありません。最初のNFDはで"o\x{332}\x{303}\x{304}"、NFCは"\x{22D}\x{332}"です。2番目のNFDはで"o\x{332}\x{304}\x{303}"、NFCは"\x{14D}\x{332}\x{303}"です。ただし、これらと標準的に同等である多くの非標準的な可能性が存在します。正規化により、正規に等価な書記素のバイナリ比較が可能になります。
tchrist

5

2つのUnicode文字列が正規に等価である場合、文字列は実際には同じであり、異なるUnicodeシーケンスのみを使用します。たとえば、Äは、文字ÄまたはAと◌̈の組み合わせを使用して表すことができます。

文字列が同等の互換性のみである場合、文字列は必ずしも同じであるとは限りませんが、状況によっては同じである場合があります。たとえば、ffはffと同じと見なすことができます。

したがって、互換性の同等性は実際の同等性ではないため、文字列を比較する場合は、正規の同等性を使用する必要があります。

しかし、文字列のセットをソートする場合は、ほとんど同じなので互換性の同等性を使用することは理にかなっています。


5

これは実際にはかなり単純です。UTF-8には、実際には同じ「文字」のいくつかの異なる表現があります。(バイト単位で異なるため、引用符で文字を使用していますが、実際には同じです)。リンク先のドキュメントに例が示されています。

文字「Ç」は、バイトシーケンス0xc387として表すことができます。ただし、C(0x43)とそれに続くバイトシーケンス0xcca7 で表すこともできます。つまり、0xc387と0x43cca7は同じ文字であると言えます。機能する理由は、0xcca7が結合マークであるためです。つまり、その前に文字が表示されます(aCここ)を変更します。

ここで、標準的な同等性と互換性の同等性の違いに関する限り、一般的に文字を調べる必要があります。

文字には2つのタイプがあり、を通して意味を伝えますものと、別の文字を取得して変更する。9は意味のある文字です。スーパースクリプト⁹は、その意味を取り、プレゼンテーションによってそれを変更します。したがって、標準的にはそれらは異なる意味を持っていますが、それでも基本キャラクターを表しています。

正規等価とは、バイトシーケンスが同じ文字を同じ意味でレンダリングする場合です。互換性の同等性とは、バイトシーケンスが同じ基本意味を持つ別の文字をレンダリングしている場合です(変更されている場合でも)。9とはどちらも「9」を意味するため互換性は同等ですが、同じ表現を持たないため、標準的には同等ではありません。


@tchrist:答えをもう一度読んでください。同じコードポイントを表すさまざまな方法については触れたこともありません。同じコンビネータと複数の文字を使用して、同じ印刷文字を表現する方法は複数あると言いました。これは、UTF-8とUnicodeの両方に適用されます。したがって、あなたの反対票とコメントは、私が言ったことにはまったく当てはまりません。実際、私は基本的にここでトップのポスターが作ったのと同じことを言っていました(それは同じではありませんが)...
ircmaxell

4

正規等価性と互換性等価性のどちらがより適切であるかは、アプリケーションによって異なります。文字列比較についてのASCIIの考え方は、大まかに標準的な同等性に対応していますが、Unicodeは多くの言語を表しています。Unicodeがすべての言語を西ヨーロッパのASCIIのように扱うことができるようにエンコードされていると想定するのは安全ではないと私は思います。

図1および2は、2つのタイプの等価の良い例を示しています。互換性の同等性の下では、サブスクリプトとスーパースクリプトの形式で同じ数を比較すると、同じように見えます。しかし、筆記体のアラビア語のフォームや回転した文字と同じ問題が解決するかどうかはわかりません。

Unicodeテキスト処理の難しい真実は、アプリケーションのテキスト処理要件を深く考えてから、利用可能なツールを使用してできる限りそれらに対処する必要があることです。それはあなたの質問に直接対処するものではありませんが、より詳細な回答では、サポートすることが期待される各言語の言語専門家が必要になります。


1

文字列比較の問題:ほとんどのアプリケーションの目的で同等の内容を持つ2つの文字列には、異なる文字シーケンスが含まれる場合があります。

Unicodeの標準的な同等性を参照してください。比較アルゴリズムが単純な(または高速でなければならない)場合、Unicodeの同等性は実行されません。この問題は、たとえば、XMLの正規比較で発生します。 。http://www.w3.org/TR/xml-c14nをください

この問題を回避するには...どの標準を使用しますか?「拡張UTF8」または「コンパクトUTF8」?
「ç」または「c +◌̧」を使用しますか?

W3Cおよびその他(ファイル名など)は、「標準として作成された」(「最もコンパクトな」短い文字列のCに留意してください)を使用することを推奨しています...

標準はCです。疑わしいNFCを使用する

相互運用性と「設定より規約」の選択については、外部文字列を「正規化」するためにNFCを使用することをお勧めします。たとえば、正規XMLを保存するには、「FORM_C」に保存します。W3CのCSV on the Webワーキンググループでも、NFCを推奨しています(セクション7.2)。

PS:de "FORM_C"は、ほとんどのライブラリのデフォルトフォームです。例 PHPのnormalizer.isnormalized()で


合成形式」(FORM_C)という用語は、「文字列がC正規形式である」(NFC変換の結果)と言うことと、変換アルゴリズムが使用されることの両方に使用されています... httpを参照してください: //www.macchiato.com/unicode/nfc-faq

(...)以下の各シーケンス(最初の2つは単一文字シーケンス)は同じ文字を表します。

  1. U + 00C5(Å)ローマ字大文字A上にリング付き
  2. U + 212B(Å)オングストローム記号
  3. U + 0041(A)ローマ字大文字A + U + 030A(̊)上記の結合リング

これらのシーケンスは、標準的に等価と呼ばれます。これらのフォームの最初のフォームはNFCと呼ばれます-正規化フォームCの場合、Cは堆肥化用です。(...)文字列SをNFC形式に変換する関数はと省略できますtoNFC(S)が、SがNFCに含まれているかどうかをテストする関数はと省略できますisNFC(S)


注:小さな文字列の正規化(純粋なUTF-8またはXMLエンティティ参照)をテストするには、このテスト/正規化オンラインコンバーターを使用できます。


よくわかりません。このオンラインテスターページにアクセスして、「TÖSTMÉpleasé」と入力しました。そして、与えられた正規化の4つすべてを試してください。これらの文字を表示するために使用されるコードが変更されることを除いて、テキストはまったく変更されません。「正規化」は「すべての発音区別記号などを削除する」ことを意味していると間違って考えているのですか、それは実際に意味しています-下のutfコーディングを変更するだけですか?
userfuser 2017年

こんにちは@userfuserおそらくアプリケーションについてのポジションが必要です。テキストを比較または標準化することですか?ここでの私の投稿は、「標準化する」アプリケーションについてのみです。PS:世界中で標準を使用すると、比較の問題はなくなります。
Peter Krauss
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.