(私はあなたの主題の質問に答えています、「同じ文字に対して2つの異なるUTF-8エンコーディングがありますか?」、これは投稿内の質問とは大きく異なります。)
(「文字」は通常、文字列要素を意味します。獣ではあいまいであり、ここで使用するのは適切な単語ではありません。視覚的表現であるグリフのUnicode用語は「書記素」です。)
はい、コードポイントのシーケンスが同じ書記素になる可能性がある以上のものがあります。たとえば、両方
U+00EB LATIN SMALL LETTER E WITH DIAERESIS
と
U+0065 LATIN SMALL LETTER E
U+0308 COMBINING DIAERESIS
「ë」と表示されます。ブラウザの動作を見てみましょう。
- U + 00EB:「ë」
- U + 0065,0308:"ë"
UTF-8では、これらのコードポイントは次のようにエンコードされます。
- U + 00EB:C3 AB
- U + 0065:65
- U + 0308:CC 88
Unicode :: Normalizeを使用するか、文字列を2つの形式のNFC
いずれかに正規化します(選択)。NFD
$ perl -MUnicode::Normalize -E'
$x = "\x{00EB}";
$y = "\x{0065}\x{0308}";
say $x eq $y ?1:0;
say NFC($x) eq NFC($y) ?1:0;
say NFD($x) eq NFD($y) ?1:0;
'
0
1
1
UTF-8には「オーバーロング」エンコーディングと呼ばれるものもあります。(具体的には、一般にUnicodeではなくUTF-8です。)UTF-8では、Unicodeコードポイントは次の4つのビットパターンのいずれかを使用してエンコードされます。
1 0xxxxxxx
2 110xxxxx 10xxxxxx
3 1110xxxx 10xxxxxx 10xxxxxx
4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
「x」は、エンコードするコードポイントを表します。可能な限り短いものを使用する必要があるため、U+00EBは次のようになります。
0000 0000 1110 1011
--- ---- ----
----- ------
110xxxxx 10xxxxxx
11000011 10101011
C3 AB
しかし、賢い人はそうするかもしれません
0000 0000 1110 1011
---- ---- ---- ----
---- ------ ------
1110xxxx 10xxxxxx 10xxxxxx
11100000 10000011 10101011
E0 83 AB
アプリケーションはE083ABを拒否する(または少なくともC3 ABに変換する)必要がありますが、拒否しないものもあり、セキュリティ上の問題を引き起こす可能性があります。PerlのEncodeモジュールはそのシーケンスを無効として扱うので、Perlの問題にはならないはずです。