戻る

Unicode 正規化

テキストツール

読み込み中

ツールを読み込んでいます

ツールのコードは開いたときにのみ読み込まれます。

このツールの処理はすべてブラウザー内で行われ、入力内容はサーバーへ送信されません。

このツールについて

見た目が同じ文字列でも、Unicode の並びが異なる場合があります。原文を保ったまま NFC・NFD・NFKC・NFKD を一度に比較し、正確なエスケープ表示、コードポイント、UTF-16 単位数、UTF-8 バイト数をローカルで確認できます。正準正規化は正準等価な列を合成または分解します。互換正規化は合字、全角文字、丸数字などの区別もまとめるため、用途に必要な意味や表記の情報を失う可能性があります。出力を選ぶ前に変化を確認してください。

主な用途

  • 別の資料からコピーしたアクセント付きの名前が、同じ見た目なのに厳密な文字列比較で一致しない理由を調べます。
  • 合成済みハングル音節と分解された結合字母を比較し、コードポイント数や UTF-8 バイト数の変化を確認します。
  • 取り込みや検索で採用する規則を決める前に、NFKC・NFKD による互換文字の追加変換を確認します。

使い方

  1. 1.実際の文字を貼り付けるか、厳密に UTF-8 で復号するローカルテキストファイルを 1 つ開き、比較を実行します。原文と 4 形式は同じ完全な入力から作られます。\u0301 のような表記は実際の結合文字を入力しない限り普通の ASCII です。下の例は正確なデータを示すために ASCII JSON を使っています。
  2. 2.変更の有無、エスケープ表示、コードポイント表示、UTF-16・UTF-8 の計数を比較します。各テキスト表示は元の UTF-16 で最大 2,000 単位、表示後の ASCII で最大 12,000 文字、U+ 列は最大 80 コードポイントです。短縮は明示され、保持した結果や完全なレポートは短縮しません。受け取り側の規則に合う形式を選び、意味を確認してください。
  3. 3.選択した結果を明示的に確認してから、完全なテキストをコピーまたは保存します。ASCII のみの JSON レポートには原文と全 4 形式を収録します。入力を変更すると前の比較と確認状態は無効になります。対にならない UTF-16 サロゲートがある場合、生テキストの出力はできませんが、エスケープ済み JSON では損失なく保持できます。

正確に再現できる正規化例

アクセント付きの列を合成する

input (ASCII JSON): "e\u0301"
{"original":{"text":"e\u0301","codePoints":2,"utf16Units":2,"utf8Bytes":3},"NFC":{"text":"\u00E9","codePoints":1,"utf16Units":1,"utf8Bytes":2},"NFD":{"text":"e\u0301","codePoints":2,"utf16Units":2,"utf8Bytes":3},"NFKC":{"text":"\u00E9","codePoints":1,"utf16Units":1,"utf8Bytes":2},"NFKD":{"text":"e\u0301","codePoints":2,"utf16Units":2,"utf8Bytes":3}}

NFC と NFKC は e と結合アキュートアクセントを U+00E9 にします。NFD と NFKD は 2 コードポイントの正準分解を保持します。

合成済みアクセント文字を分解する

input (ASCII JSON): "\u00E9"
{"original":{"text":"\u00E9","codePoints":1,"utf16Units":1,"utf8Bytes":2},"NFC":{"text":"\u00E9","codePoints":1,"utf16Units":1,"utf8Bytes":2},"NFD":{"text":"e\u0301","codePoints":2,"utf16Units":2,"utf8Bytes":3},"NFKC":{"text":"\u00E9","codePoints":1,"utf16Units":1,"utf8Bytes":2},"NFKD":{"text":"e\u0301","codePoints":2,"utf16Units":2,"utf8Bytes":3}}

NFD と NFKD は U+00E9 を e と結合アキュートアクセントに分解します。見た目が似ていてもバイト数は変わります。

ハングル音節を分解する

input (ASCII JSON): "\uAC01"
{"original":{"text":"\uAC01","codePoints":1,"utf16Units":1,"utf8Bytes":3},"NFC":{"text":"\uAC01","codePoints":1,"utf16Units":1,"utf8Bytes":3},"NFD":{"text":"\u1100\u1161\u11A8","codePoints":3,"utf16Units":3,"utf8Bytes":9},"NFKC":{"text":"\uAC01","codePoints":1,"utf16Units":1,"utf8Bytes":3},"NFKD":{"text":"\u1100\u1161\u11A8","codePoints":3,"utf16Units":3,"utf8Bytes":9}}

NFD と NFKD は U+AC01 を U+1100 U+1161 U+11A8 の 3 つの結合字母に分解し、UTF-8 で 9 バイトになります。

合字・文字幅・丸数字の区別を確認する

input (ASCII JSON): "\uFB03\uFF21\u2460"
{"original":{"text":"\uFB03\uFF21\u2460","codePoints":3,"utf16Units":3,"utf8Bytes":9},"NFC":{"text":"\uFB03\uFF21\u2460","codePoints":3,"utf16Units":3,"utf8Bytes":9},"NFD":{"text":"\uFB03\uFF21\u2460","codePoints":3,"utf16Units":3,"utf8Bytes":9},"NFKC":{"text":"ffiA1","codePoints":5,"utf16Units":5,"utf8Bytes":5},"NFKD":{"text":"ffiA1","codePoints":5,"utf16Units":5,"utf8Bytes":5}}

互換形式だけが U+FB03 U+FF21 U+2460 を ffiA1 にします。その結果だけから元の区別は復元できません。

長さを変えず結合文字を並べ替える

input (ASCII JSON): "q\u0307\u0323"
{"original":{"text":"q\u0307\u0323","codePoints":3,"utf16Units":3,"utf8Bytes":5},"NFC":{"text":"q\u0323\u0307","codePoints":3,"utf16Units":3,"utf8Bytes":5},"NFD":{"text":"q\u0323\u0307","codePoints":3,"utf16Units":3,"utf8Bytes":5},"NFKC":{"text":"q\u0323\u0307","codePoints":3,"utf16Units":3,"utf8Bytes":5},"NFKD":{"text":"q\u0323\u0307","codePoints":3,"utf16Units":3,"utf8Bytes":5}}

全形式で下付きドットが上付きドットより前になります。3 種類の計数は同じでも、列の順序は変わります。

CRLF と絵文字列を保持する

input (ASCII JSON): "A\r\n\uD83D\uDC69\u200D\uD83D\uDCBB\u2764\uFE0F"
{"original":{"text":"A\r\n\uD83D\uDC69\u200D\uD83D\uDCBB\u2764\uFE0F","codePoints":8,"utf16Units":10,"utf8Bytes":20},"NFC":{"text":"A\r\n\uD83D\uDC69\u200D\uD83D\uDCBB\u2764\uFE0F","codePoints":8,"utf16Units":10,"utf8Bytes":20},"NFD":{"text":"A\r\n\uD83D\uDC69\u200D\uD83D\uDCBB\u2764\uFE0F","codePoints":8,"utf16Units":10,"utf8Bytes":20},"NFKC":{"text":"A\r\n\uD83D\uDC69\u200D\uD83D\uDCBB\u2764\uFE0F","codePoints":8,"utf16Units":10,"utf8Bytes":20},"NFKD":{"text":"A\r\n\uD83D\uDC69\u200D\uD83D\uDCBB\u2764\uFE0F","codePoints":8,"utf16Units":10,"utf8Bytes":20}}

全形式で CRLF、女性プログラマーの ZWJ 列、ハートの異体字セレクターを保持します。UTF-16 の 10 単位は 8 コードポイント、UTF-8 の 20 バイトに対応します。

対のないサロゲートを JSON に保持する

input (ASCII JSON): "A\uD800B"
{"original":{"text":"A\uD800B","codePoints":3,"utf16Units":3,"utf8Bytes":null},"NFC":{"text":"A\uD800B","codePoints":3,"utf16Units":3,"utf8Bytes":null},"NFD":{"text":"A\uD800B","codePoints":3,"utf16Units":3,"utf8Bytes":null},"NFKC":{"text":"A\uD800B","codePoints":3,"utf16Units":3,"utf8Bytes":null},"NFKD":{"text":"A\uD800B","codePoints":3,"utf16Units":3,"utf8Bytes":null}}

全形式で対のない U+D800 を保持します。UTF-8 長は null で生テキストのコピーと保存はできませんが、ASCII JSON には正確な列が残ります。

エスケープ表記を普通の文字として保つ

input (ASCII JSON): "e\\u0301"
{"original":{"text":"e\\u0301","codePoints":7,"utf16Units":7,"utf8Bytes":7},"NFC":{"text":"e\\u0301","codePoints":7,"utf16Units":7,"utf8Bytes":7},"NFD":{"text":"e\\u0301","codePoints":7,"utf16Units":7,"utf8Bytes":7},"NFKC":{"text":"e\\u0301","codePoints":7,"utf16Units":7,"utf8Bytes":7},"NFKD":{"text":"e\\u0301","codePoints":7,"utf16Units":7,"utf8Bytes":7}}

入力はバックスラッシュを含む 7 つの ASCII 文字です。この表記を結合アクセントとして評価することはありません。

空の入力を調べる

input (ASCII JSON): ""
{"original":{"text":"","codePoints":0,"utf16Units":0,"utf8Bytes":0},"NFC":{"text":"","codePoints":0,"utf16Units":0,"utf8Bytes":0},"NFD":{"text":"","codePoints":0,"utf16Units":0,"utf8Bytes":0},"NFKC":{"text":"","codePoints":0,"utf16Units":0,"utf8Bytes":0},"NFKD":{"text":"","codePoints":0,"utf16Units":0,"utf8Bytes":0}}

空文字列は全形式で空のままで、コードポイント数、UTF-16 単位数、UTF-8 バイト数はすべてゼロです。

正規化で起こりやすい誤解

  • 多くの文字を変換できるという理由だけで NFKC を選び、表記や意味の区別の喪失を確認しないこと。
  • 合成文字、結合文字列、絵文字クラスタの UTF-16・UTF-8 長が同じだと思うこと。
  • 計数が同じなら文字列も同じだと考えること。正準的な並べ替えでは長さを保ったまま順序が変わります。
  • ASCII の \uXXXX という表記が自動的に文字へ復号されると期待すること。
  • 正規化を安全化、翻訳、大小文字の統合、本人確認の証拠として使うこと。
  • エスケープで秘密が削除されたと思い込み、完全なレポートを共有すること。

制限と注意事項

  • NFC は正準分解の後に正準合成を行い、NFD は正準分解を行います。NFKC・NFKD は互換分解も適用し、NFKC はその後に合成します。互換変換は一般に可逆ではなく、合字、文字幅、丸数字などの区別が失われます。正規化はアクセント除去、翻訳、翻字、大文字小文字の変換ではなく、異なる文字列の意図が同じだと証明するものでもありません。
  • 実装は現在のブラウザー実行環境の String.prototype.normalize と、その Unicode 対応範囲を使います。Unicode 17 の正規化データベースを同梱せず、固定 Unicode バージョンも保証しません。実行環境がまだ認識しない新しい文字では結果が異なる場合があります。新規割り当て文字の再現性が必要なら、バージョンを明示した後段の実装を使ってください。
  • コードポイント数は見た目の文字数、書記素クラスタ数、表示幅とは異なり、1 つの絵文字列に複数のコードポイントが含まれます。補助平面の文字は UTF-16 を 2 単位使います。対にならないサロゲートは保持して診断用の疑似単位として 1 つ数えますが、Unicode スカラー値ではありません。その UTF-8 長は利用できず、U+FFFD への暗黙の置換を避けるため生テキストのコピーと保存を禁止します。 変更の詳細は共通のコードポイント接頭部・接尾部の間にある 1 つの包括的な範囲であり、最小の編集一覧ではありません。範囲内に未変更の部分を含む場合があります。位置はゼロ始まりで終端を含まず、有効なサロゲート対を分割しません。
  • 正規化はサニタイズ、紛らわしい文字や同形文字の検出、マルウェア解析、識別子検証、安全性の判定ではありません。不可視文字、双方向制御文字、絵文字の結合子、異体字セレクターを任意に削除しません。コアに渡された CR と LF は保持しますが、貼り付けやクリップボードがツール外で改行を変える場合があります。厳密な改行が必要ならファイル入力とダウンロードを優先してください。
  • 処理は上限を設けたローカル処理です。入力は UTF-16 で最大 20,000 単位、UTF-8 ファイルは最大 80,000 バイト、各正規化結果は UTF-16 で最大 360,000 単位、原文と全 4 形式の合計は最大 1,460,000 単位です。ASCII JSON レポートは最大 10,000,000 文字です。入力のアップロード、ネットワーク照会、永続保存は行いません。不正な UTF-8 ファイルは置換して続行せず拒否し、先頭 BOM は U+FEFF として保持します。処理やレポートの上限を超えると明示的にエラーにし、出力を黙って切り詰めません。ASCII エスケープは可逆な表現であり、墨消しや暗号化ではありません。レポートには個人情報を含め、完全な原文と正規化結果が入ります。

よくある質問

どの正規化形式を選べばよいですか?

受け取り側のシステムの仕様に従ってください。NFC は通常、合成された正準表現を、NFD は分解された表現を作ります。NFKC・NFKD は互換上の区別もまとめるため、別途意味の確認が必要です。このツールは全形式を比較し、どれか 1 つを常に正しいと決めつけません。 いいえ。合成は Unicode の規則に制約され、一部の文字は合成対象から除外されます。結合文字の順序だけが変わり、コードポイント数やバイト数が変わらない場合もあります。長さだけで判断せず、正確な結果を確認してください。

NFKC は疑わしい文字列を安全にし、似た文字をすべて統一しますか?

いいえ。互換正規化は完全なセキュリティ機構でも、紛らわしい文字の検出器でもありません。例えばラテン文字とキリル文字は似ていても異なるままの場合があります。用途に合う識別子の規則とセキュリティ検証は別に確認してください。

テキストを保存できないのに JSON を保存できるのはなぜですか?

対にならない UTF-16 サロゲートは、置換せずに有効な UTF-8 として符号化できません。診断用 JSON は ASCII エスケープを使って、原文と全形式の正確なコード単位を保持します。エスケープしても入力が修復されたり、安全になったりするわけではありません。

空白、絵文字、改行は自動的に整理されますか?

追加の整理処理はありません。互換正規化は改行しない空白など互換写像のある文字を変換できますが、正準正規化は一般的な空白置換を行いません。CRLF、絵文字の結合子、異体字セレクターは削除しません。出力前に実際のコードポイントを確認してください。

関連ツール