93

กิิิิิิิิิิิิิิิิิิิิก้้็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็กิิิิิิิิิิิิิิิิิิิิก้้ก็กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้ก็ก็็็็็็็็็็็็็็็็็็็็ก็ก็็็็็็็็็็็็็็็็็็็็กิิิิิิิิิิิิิิิิิิิิกิิิิิิิิิิิิิิิิิิิิกิิิิิิิิิิิิิิิิิิิิก้้ก้้้้้้้้้้้้้้้้้้้้ก็้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้</p> </p>

这些最近出现在 Facebook 评论部分。

我们如何对其进行消毒?

4

4 回答 4

81

这些 un​​icode 字符是怎么回事?

那是一个具有一系列组合字符的字符。因为有问题的组合字符想要超过基本字符,所以它们堆叠起来(字面意思)。例如,案例

ก้้้้้้้้้้้้้้้้้้้้</p>

...这是一个 ก(泰语字符ko kai)(U+0E01),后跟 20 个泰语组合字符mai thoU+0E49)。

我们如何对其进行消毒?

可以预处理文本并限制可应用于单个字符的组合字符的数量,但这种努力可能不值得回报。您需要所有当前字符的数据表,以便知道它们是组合还是什么,并且您需要确保至少允许一些字符,因为某些语言是在一个基础上使用多个变音符号编写的. 现在,如果您想将评论限制为拉丁字符集,那将是一个更简单的范围检查,但当然,如果您想将评论限制为仅几种语言,这只是一种选择。unicode.org上的更多信息、代码表等。

顺便说一句,如果您想知道某个字符是如何组成的,那么对于最近的另一个问题,我在 JSBin 上编写了一个快速而肮脏的“Unicode Show Me”页面。您只需将文本复制并粘贴到文本区域中,它就会向您显示构成文本的所有代码点(~字符),以及上面描述每个字符的页面的链接。它仅适用于 U+FFFF 及以下范围内的代码点,因为它是用 JavaScript 编写的,并且要在 JavaScript 中处理 U+FFFF 以上的字符,您必须做的工作比我想为该问题做的要多(因为在 JavaScript 中,一个“性格”总是16 位,这意味着对于某些语言,一个字符可以分成两个单独的 JavaScript“字符”,我没有考虑到这一点),但对于大多数文本来说它很方便......

于 2012-05-02T13:42:44.883 回答
17

如果您有一个支持良好 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");

这将打印:

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

于 2013-03-12T18:33:33.193 回答
14

TJ Crowder最好在上面回答“我们如何对其进行消毒”

但是,我认为清理是错误的方法,Cristyoverflow:hidden在包含 css 的元素上是 正确的。

至少,我就是这样解决它的。

于 2013-03-12T18:00:08.830 回答
6

好的,这花了我一段时间才弄清楚,我的印象是组合字符来产生 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 上缺少的一个范围是06D6-06DC另一个0730-0749.

更新:

这是更新的正则表达式,它应该找出所有的 zalgo,包括那些在“正常”范围内绕过的 zalgo。

([\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,})

最难的是识别它们,一旦你做到了——有很多解决方案,包括上面的一些好的解决方案。

希望这可以节省您一些时间。

于 2016-03-17T12:38:48.923 回答