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

Cri*_*sty 89 unicode sanitize combining-marks zalgo

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

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

我们怎样才能消毒这个?

T.J*_*der 80

这些unicode角色怎么了?

这是一个具有一系列组合字符的角色.因为所讨论的组合字符想要超过基本字符,所以它们会叠加(字面意思).例如,的情况

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

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

我们怎样才能消毒这个?

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

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

  • @RemyLebeau:*"你什么时候需要不止一次将相同的代码点组合到一个基本代码点?"*我不知道,我对你如何编写其他语言非常非常了解 - 例如泰语.我发现不止一个相同的代码点在某些代码中是有效的,我也不会感到惊讶.但这样做并不会降低复杂性; 你仍然需要一个Unicode表来确定哪些是组合字符. (4认同)
  • JavaScript库可以轻松地从字符串中删除Unicode组合标记:http://mths.be/stripcombiningmarks (2认同)

nwe*_*hof 18

如果你有一个具有良好的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");
Run Code Online (Sandbox Code Playgroud)

这将打印:

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

  • 我不会读藏语,但我担心这种强力方法可能会从语言设计的方式中删除功能.我见过unicode,它具有多个组合标记的合法用例.阿拉伯语是一个很好的例子 我会记得由我的藏族同事来管理这件事. (9认同)
  • 你是对的,肯定存在多个组合标记合法的情况.但您可以轻松更改正则表达式以允许一定的最大标记. (2认同)

Fli*_*McF 12

"我们如何消毒这个"最好由TJ Crowder在上面回答

但是,我认为清理是错误的方法,而Cristyoverflow:hidden对包含css的元素 有正确的认识.

至少,这就是我解决它的方式.


Mat*_*ius 7

好吧,这个让我花了一段时间才弄明白,我的印象是,将角色组合起来制作zalgo 仅限于这些.所以我期待跟随正则表达式捕捉怪胎.

([\u0300–\u036F\u1AB0–\u1AFF\u1DC0–\u1DFF\u20D0–\u20FF\uFE20–\uFE2F]{2,})
Run Code Online (Sandbox Code Playgroud)

它不起作用......

问题是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>");
    }
Run Code Online (Sandbox Code Playgroud)

通过查看生成的表,您应该能够看到哪些堆栈.维基上缺少的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,})
Run Code Online (Sandbox Code Playgroud)

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

希望这能为您节省一些时间.

  • @PraveenKumar这个问题没有陈述一种语言,如果旧的答案在某些方面存在缺陷,那么在旧问题上发布新答案是完全合适的.不幸的是,我没有足够的经验来解决这个问题,或者它会得到我的支持. (7认同)
  • @PraveenKumar它揭示了为什么正常的zalgo验证`([\ u0300-\u036F\u1AB0-\u1AFF\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F] {2,})``不起作用.难道你不觉得堆叠unicode不仅限于维基上的什么有趣吗?"丢失的回答问题"是什么意思?**编辑**:您可能会觉得添加3岁问题的答案很奇怪,但是因为我花了一段时间才弄清楚为什么这种类型的zalgo有效,所以我不能让这些知识浪费掉.下一个人会节省一些时间. (4认同)