web-dev-qa-db-ja.com

これらのUnicode結合文字の最新情報と、それらをフィルタリングする方法を教えてください。

กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้ก็็็็็็็็็็็็็็็็็็็็ก็็็็็็็็็็็็็็็็็็็็กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้ก็็็็็็็็็็็็็็็็็็็็กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้ก็็็็็็็็็็็็็็็็็็็็ก็็็็็็็็็็็็็็็็็็็็กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้ก็็็็็็็็็็็็ ็็็็็็็กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้

これらは最近Facebookのコメントセクションに表示されました。

これをどのようにサニタイズできますか?

88
Cristy

これらのUnicode文字はどうなっていますか?

それは一連の 結合文字 を持つ文字です。問題の結合文字はベース文字の上に移動したいので、(文字通り)スタックします。たとえば、

ก้้้้้้้้้้้้้้้้้้้้

...それはก(タイ文字ko kai)( + 0E01 )に続いてタイ語の組み合わせが20コピー文字mai tho(- + 0E49 ).

これをどのようにサニタイズできますか?

あなたはcouldテキストを前処理し、単一のキャラクターに適用できる結合キャラクターの数を制限しますが、努力は報われる価値がないかもしれません。現在のすべてのキャラクターのデータシートが必要なので、それらが結合しているかどうかを知っている必要があります。また、いくつかの言語は単一のベースでいくつかの発音区別符号で書かれているため、少なくともいくつかを許可する必要があります。これで、コメントをラテン文字セットに制限したい場合は、範囲チェックが簡単になりますが、もちろん、コメントをいくつかの言語に制限したい場合のオプションにすぎません。 nicode.org の詳細情報、コードシートなど。

ところで、あるキャラクターがどのように作られたのか知りたいのなら、最近別の質問のために、JSBinで quick-and-dirty "Unicode Show Me"ページ をコーディングしました。テキストをコピーしてテキスト領域に貼り付けるだけで、テキストが構成されているすべてのコードポイント(〜文字)が表示され、各文字を説明するページへのリンクなどが表示されます。 U + FFFF以下の範囲のコードポイントでのみ機能します。JavaScriptで記述されており、JavaScriptでU + FFFFを超える文字を処理するには、その質問に対して行うよりも多くの作業を行う必要があります(JavaScriptの場合、 「文字」はalways16ビットです。これは、一部の言語では、文字を2つの個別のJavaScript「文字」に分割できることを意味します。それ)、しかし、それはほとんどのテキストに便利です...

80
T.J. Crowder

適切なUnicodeサポートを備えた正規表現エンジンがある場合、この種の文字列をサニタイズするのは簡単です。たとえば、Perlでは、次のように、すべての(ユーザーが認識した)文字から最初の結合マーク以外のすべてを削除できます。

#!/usr/bin/Perl
use strict;
use utf8;

binmode(STDOUT, ':utf8');

my $string = "กิิ ก้้ ก็็ ก็็ กิิ ก้้ ก็็ กิิ ก้้ กิิ ก้้ ก็็ ก็็ กิิ ก้้ ก็็ กิิ ก้้";
$string =~ s/(\p{Mark})\p{Mark}+/$1/g; # Strip excess combining marks
print("$string\n");

これは印刷されます:

กิก้ก็ก็กิก้ก็กิก้กิก้ก็ก็กิก้ก็กิก้

18
nwellnhof

「これをどのようにサニタイズできますか」は、上記で T.J Crowder

ただし、サニタイズは間違ったアプローチであり、 Cristyoverflow:hidden要素を含むcssで。

少なくとも、それは私がそれを解決している方法です。

12
FlipMcF

これを理解するのに少し時間がかかりました。キャラクターを組み合わせてzalgoを生成するのは これらに限定 であるという印象を受けました。だから、私は 正規表現に続く がフリークを捕まえると期待した。

_([\u0300–\u036F\u1AB0–\u1AFF\u1DC0–\u1DFF\u20D0–\u20FF\uFE20–\uFE2F]{2,})
_

うまくいかなかった...

問題は、 wikiのリスト が結合文字の全範囲をカバーしていないことです。

ヒントをくれたのは"ก้้้้้้้้้้้้้้้้้้้้".charCodeAt(2).toString(16) = "e49"で、これは結合の範囲内ではなく、「プライベート使用」に該当します。

C#では、それらは_UnicodeCategory.NonSpacingMark_に該当し、次のスクリプトはそれらをフラッシュします。

_    [Test]
    public void IsZalgo()
    {
        var zalgo = new[] { UnicodeCategory.NonSpacingMark };

        File.Delete("IsModifyLike.html");
        File.AppendAllText("IsModifyLike.html", "<table>");
        for (var i = 0; i < 65535; i++)
        {
            var c = (char)i;
            if (zalgo.Contains(Char.GetUnicodeCategory(c)))
            {


                File.AppendAllText("IsModifyLike.html", string.Format("<tr><td>{0}</td><td>{1}</td><td>{2}</td><td>A&#{3};&#{3};&#{3}</td></tr>\n",  i.ToString("X"), c, Char.GetUnicodeCategory(c), i));

            }
        }
        File.AppendAllText("IsModifyLike.html", "</table>");
    }
_

生成されたテーブルを見ると、どのテーブルがスタックしているかがわかるはずです。 Wikiにない1つの範囲は_06D6-06DC_別の_0730-0749_です。

UPDATE:

ここに更新された正規表現 これは、「通常の」範囲でバイパスされたものを含むすべてのザルゴを釣るはずです。

_([\u0300–\u036F\u1AB0–\u1AFF\u1DC0–\u1DFF\u20D0–\u20FF\uFE20–\uFE2F\u0483-\u0486\u05C7\u0610-\u061A\u0656-\u065F\u0670\u06D6-\u06ED\u0711\u0730-\u073F\u0743-\u074A\u0F18-\u0F19\u0F35\u0F37\u0F72-\u0F73\u0F7A-\u0F81\u0F84\u0e00-\u0eff\uFC5E-\uFC62]{2,})
_

最も難しいのは、一度それを特定することです-上記のいくつかの優れたソリューションを含む多数のソリューションがあります。

これで時間を節約できることを願っています。

7