这些Unicode组合字符有什么作用,我们如何过滤它们?


91

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

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

我们该如何消毒呢?


5
你没问过这个问题吗?(诚​​实的问题。)
Ry-

5
那些绝对不是ascii
克里斯·埃伯

31
为什么要结束投票?这是一个与编程有关的问题,因为我想知道如何清除这种输入,因此我网站上的评论部分不会成为13岁的孩子……
XCS

17
”“所以我网站上的评论版块不会是13岁儿童的游乐场。” 实际上,如果不进行消毒,则张贴这些字符可能会使上面的注释不可读,这根本不是令人愉快的用户体验。
XCS 2012年

14
@pjotr绝对不是浏览器错误。如果你想字符不溢出容器盒,你可以简单地解决与CSS(溢出:隐藏;)...
XCS

Answers:


80

这些unicode字符怎么了?

那是一个带有一系列组合字符的字符。因为所讨论的组合字符要高于基本字符,所以它们会堆叠在一起(字面上)。例如,

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

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

我们该如何消毒呢?

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

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


1
您是否只是将同一组合代码点的重复副本背对背删除为单个副本?您何时需要将同一代码点多次合并到基本代码点?
雷米·勒博

4
@RemyLebeau:“何时需要将同一代码点多次组合到基本代码点上?” 我不知道,我对您如何编写其他语言(例如泰语)了解得很少。如果发现在某些代码点中有多个相同的代码点,我将不感到惊讶。但是这样做并不能降低复杂性。您仍然需要Unicode表之一来确定哪些表正在组合字符。
TJ Crowder

我做你的页面接受来自URL例如unicode字符串jsbin.com/erajer/7/...
ubershmekel

2
JavaScript库可轻松从字符串中删除Unicode组合标记:mths.be/stripcombiningmarks
Mathias Bynens 2014年

JavaScript使用UTF-16« 代理对 »
石棚

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");

这将打印:

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


9
我看不懂藏语,但我担心这种蛮力方法可能会从语言的设计方式中删除功能。我见过Unicode具有多个组合标记的合法用例。阿拉伯语就是一个很好的例子。我会尽量记住由我的藏族同事来办。
FlipMcF

2
没错,在某些情况下,多个组合标记是合法的。但是,您可以轻松更改正则表达式以允许一定数量的标记。
nwellnhof 2013年

由于它确实回答了“您如何对此消毒”的问题,因此被推荐。但是我认为这将是一场维护噩梦。
FlipMcF

同样,RE仅删除相邻的重复项。说不会清理<base><macron><overline><macron><overline>...。因此,如果您的文本需要多个不同的组合字符,则可以顺利通过;并且仍然可以构建恶意文本。
杰西·奇斯霍尔姆

13

上面的TJ Crowder最好地回答了“我们该如何消毒”

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

至少,这就是我要解决的方法。


6

好的,这花了我一段时间,我给人留下了深刻的印象,那就是将字符组合成zalgo 仅限于这些。因此,我期望遵循regex来抓狂。

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

通过查看生成的表,您应该能够看到哪些堆栈。维基上缺少的一个范围是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,})

一旦完成,最困难的是识别它们-上面有很多好的解决方案。

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


我会说,不要给这个垃圾邮件发送垃圾邮件!
Praveen Kumar Purushothaman

@PraveenKumar您是否愿意详细说明您的意思?
Matas Vaitkevicius

非常感谢您的回答,但这是一个遗失的问题。那么,为什么要不必要地添加新答案呢?这只是我的看法。而且,您的答案不是JavaScript,对吗?
Praveen Kumar Purushothaman

4
@PraveenKumar它揭示了正常的zalgo验证([\u0300–\u036F\u1AB0–\u1AFF\u1DC0–\u1DFF\u20D0–\u20FF\uFE20–\uFE2F]{2,})不起作用的原因。您是否感到有趣的是,堆叠unicode不仅限于wiki上的内容?“失去答案的问题”是什么意思?编辑:您可能会发现对3年之久的问题添加答案很奇怪,但是由于花了我一段时间才弄清楚这种类型的zalgo为何起作用,所以我不能浪费这种知识。下一个家伙会节省一些时间。
Matas Vaitkevicius

7
@PraveenKumar该问题没有陈述语言,并且如果旧答案在某种程度上存在缺陷,则在旧问题上发布新答案是完全合适的。不幸的是,我没有足够的经验来解决这个问题,否则我将无法接受。
Mark Ransom
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.