5

PHPコードで絵文字を検出し、ユーザーが絵文字を入力できないようにしようとしています。

私が持っているコードは次のとおりです。

if(preg_match('/\xEE[\x80-\xBF][\x80-\xBF]|\xEF[\x81-\x83][\x80-\xBF]/', $value) > 0)
{
    //warning...
}

ただし、すべての絵文字で機能するわけではありません。何か案は?

4

5 に答える 5

10
if(preg_match('/\xEE[\x80-\xBF][\x80-\xBF]|\xEF[\x81-\x83][\x80-\xBF]/', $value) 

UTF-8バイトシーケンスを追跡しようとするのではなく、実際には文字レベルでUnicodeを照合する必要があります。u修飾子を使用して、UTF-8文字列を文字ベースで処理します。

絵文字はブロックU+1F300–U+1F5FFにエンコードされています。でも:

  • 日本のキャリアの「絵文字」セットの多くの文字は、実際には既存のUnicode記号にマッピングされています。たとえば、カードスーツ、星座、いくつかの矢印などです。これらの記号を「絵文字」として数えますか?

  • 新しく標準化されたUnicode絵文字コードポイントを使用せず、代わりに私用面でアドホック範囲を使用するシステムがまだあります。各キャリアには独自のエンコーディングがありました。iOS4はソフトバンクセットを使用しました。より詳しい情報。私用面全体をブロックすることをお勧めします。

例えば:

function unichr($i) {
    return iconv('UCS-4LE', 'UTF-8', pack('V', $i));
}

if (preg_match('/['.
    unichr(0x1F300).'-'.unichr(0x1F5FF).
    unichr(0xE000).'-'.unichr(0xF8FF).
']/u'), $value) {
    ...
}
于 2012-05-14T13:41:19.797 に答える
2

ウィキペディアから:

Unicode 6.0 のコア絵文字セットは 722 文字で構成され、そのうち 114 文字は 6.0 より前の Unicode 標準の 1 つまたは複数の文字のシーケンスにマップされ、残りの 608 文字は Unicode 6.0 で導入された 1 つまたは複数の文字のシーケンスにマップされます。 .[4] 絵文字専用に用意されたブロックはありません。新しい記号は 7 つの異なるブロック (一部は新しく作成されたブロック) でエンコードされ、EmojiSources.txt と呼ばれる Unicode データ ファイルが存在します。これには、日本のベンダーの従来の文字セットとのマッピングが含まれています。

マッピング ファイルは次のとおりです。ファイルには 722 行あり、それぞれが 722 個の顔文字の 1 つを表しています。

絵文字用に確保された特定のブロックがないため、これは簡単なことではないようです。すべての絵文字ユニコードをカバーするように正規表現を調整する必要があります。

次のように、個々の unicode を一致させることができます。

\x{1F30F}

1F30F は、地球の顔文字の Unicode です。

申し訳ありませんが、完全な答えはありませんが、これで正しい方向に進むはずです。

于 2012-05-12T17:58:00.060 に答える
1

正しい答えは、Miscellaneous_Symbols_And_Pictographsブロック内の割り当てられたコード ポイントがある場所を検出することです。Perlでは、次を使用します

 /\p{Assigned}/ && \p{block=Miscellaneous_Symbols_And_Pictographs}/

あるいは単に

/\P{Cn}/ && /\p{Miscellaneous_Symbols_And_Pictographs}/

それらを1つのパターンに組み合わせる必要があります

/(?=\p{Assigned})\p{Miscellaneous_Symbols_And_Pictographs}/

PHP が使用する PCRE ライブラリが、必要な Unicode 文字プロパティへのアクセスを提供するかどうかは覚えていません。私の記憶では、その特定の分野ではかなり弱いということです。Unicode スクリプトのプロパティと一般的なカテゴリしかないと思います。はぁ。

時には本物を使うしかない。

適切な Unicode サポートがないため、自分でブロックを列挙する必要がある場合があります。

/(?=\P{Cn})[\x{1F300}-\x{1F5FF}]/

魔法の数字でいっぱいのメンテナンスの悪夢のように見えます。

于 2012-05-13T01:00:36.790 に答える
-2

それが今日私が思いついたものです。おそらくこの問題の良い解決策ではありませんが、少なくとも機能します;)

if(iconv('Windows-1250', 'UTF-8', iconv('UTF-8', 'Windows-1250', $value)) != $value)
于 2012-05-13T13:45:02.237 に答える