Điều gì xảy ra với các ký tự kết hợp Unicode này và làm thế nào chúng ta có thể lọc chúng?


91

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

Những điều này gần đây đã xuất hiện trong phần bình luận trên facebook.

Làm thế nào chúng ta có thể làm sạch nó?


5
Bạn chưa hỏi câu hỏi này bao giờ? (Câu hỏi trung thực.)
Ry-

5
Đó chắc chắn không phải là ascii
Chris Eberle

31
Tại sao các phiếu bầu đóng? Đó là một câu hỏi liên quan đến lập trình, vì tôi muốn biết cách khử trùng loại đầu vào này để các phần bình luận trên trang web của tôi sẽ không phải là sân chơi của những đứa trẻ 13 tuổi ...
XCS

17
กิิิิิิิิิิิิิิิิิิิิ ก้้้้้้้้้้้้้้้้้้้้ ก็็็็็็็็็็็็็็็็็็็็ ก็็็็็็็็็็็็็็็็็็็็ กิิิิิิิิิิิิิิิิิิิิ ก้้้้้้้้้้้้้้้้้้้้ ก็็็็็็็็็็็็็็็็็็็็ กิิิิิิิิิิิิิิิิิิิิ ก้้้้้้้้้้้้้้้้้้้้ กิิิิิิิิิิิิิิิิิิิิ ก้้้้้้้้้้้้้้้้้้้้ ก็็็็็็็็็็็็็็็็็็็็ ก็็็็็็็็็็็็็็็็็็็็ กิิิิิิิิิิิิิิิิิิิิ ก้้้้้้้้้้้้้้้้้้้้ ก็็็็็็็็็็็็็็็็็็็็ กิิิิิิิิิิิิิิิ "nên các phần bình luận trên trang web của tôi sẽ không phải là sân chơi của những đứa trẻ 13 tuổi." Trên thực tế, nếu không có sự khử trùng, một người đăng những ký tự này có thể làm cho nhận xét ở trên nó không thể đọc được, điều này hoàn toàn không phải là một trải nghiệm người dùng dễ chịu.
XCS

14
@pjotr Nó rõ ràng không phải là lỗi của trình duyệt. Nếu bạn muốn các ký tự không tràn hộp chứa, bạn có thể đơn giản giải quyết điều đó bằng CSS (tràn: ẩn;) ...
XCS

Câu trả lời:


80

Chuyện gì xảy ra với những ký tự unicode này?

Đó là một nhân vật với một loạt các ký tự kết hợp . Bởi vì các ký tự kết hợp được đề cập muốn vượt lên trên ký tự cơ sở, chúng xếp chồng lên nhau (theo nghĩa đen). Ví dụ, trường hợp của

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

... đó là một ก (ký tự Thái ko kai ) ( U + 0E01 ) theo sau là 20 bản sao của ký tự Thái kết hợp mai tho ( U + 0E49 ).

Làm thế nào chúng ta có thể làm sạch nó?

Bạn có thể xử lý trước văn bản và giới hạn số lượng ký tự kết hợp có thể được áp dụng cho một ký tự duy nhất, nhưng nỗ lực có thể không xứng đáng với phần thưởng. Bạn sẽ cần các bảng dữ liệu cho tất cả các ký tự hiện tại để bạn biết liệu chúng có đang kết hợp hay không và bạn cần đảm bảo cho phép ít nhất một vài ký tự vì một số ngôn ngữ được viết với nhiều dấu phụ trên một cơ sở duy nhất . Bây giờ, nếu bạn muốn giới hạn nhận xét trong bộ ký tự Latinh, đó sẽ là một kiểm tra phạm vi dễ dàng hơn, nhưng tất nhiên đó chỉ là một tùy chọn nếu bạn muốn giới hạn nhận xét chỉ trong một vài ngôn ngữ. Thêm thông tin, bảng mã, v.v. tại unicode.org .

BTW, nếu bạn muốn biết một số ký tự được tạo ra như thế nào, đối với một câu hỏi khác gần đây tôi đã viết mã một trang "Unicode Show Me" nhanh và bẩn thỉu trên JSBin. Bạn chỉ cần sao chép và dán văn bản vào vùng văn bản và nó hiển thị cho bạn tất cả các điểm mã (~ ký tự) mà văn bản được tạo thành, với các liên kết như ở trên đến trang mô tả từng ký tự. Nó chỉ hoạt động cho các điểm mã trong phạm vi U + FFFF trở xuống, bởi vì nó được viết bằng JavaScript và để xử lý các ký tự trên U + FFFF trong JavaScript, bạn phải làm nhiều việc hơn tôi muốn làm cho câu hỏi đó (bởi vì trong JavaScript, a "nhân vật" luôn luôn 16 bit, có nghĩa là đối với một số ngôn ngữ, một ký tự có thể được chia thành hai "ký tự" JavaScript riêng biệt và tôi không tính đến điều đó), nhưng nó tiện dụng cho hầu hết các văn bản ...


1
Bạn sẽ không chỉ xóa các bản sao lặp đi lặp lại của cùng một điểm kết hợp trở lại thành một bản sao duy nhất? Khi nào bạn cần kết hợp cùng một điểm mã vào một điểm cơ sở nhiều hơn một lần?
Remy Lebeau

4
@RemyLebeau: "Khi nào bạn cần kết hợp cùng một điểm hẹn vào một điểm cơ sở nhiều hơn một lần?" Tôi không biết, tôi biết rất ít về cách bạn viết các ngôn ngữ khác - chẳng hạn như tiếng Thái. Tôi sẽ không ngạc nhiên khi phát hiện ra rằng nhiều hơn một điểm mã giống nhau là hợp lệ trong một số. Nhưng làm điều đó không làm giảm sự phức tạp; bạn vẫn cần một trong các bảng Unicode để tìm ra bảng nào đang kết hợp các ký tự.
TJ Crowder

Tôi đã làm cho trang của bạn chấp nhận chuỗi unicode từ url, ví dụ: jsbin.com/erajer/7/…
ubershmekel Ngày

2
Thư viện Javascript để dễ dàng loại bỏ Unicode kết hợp dấu từ chuỗi: mths.be/stripcombiningmarks
Mathias Bynens

JavaScript sử dụng UTF-16 với « cặp thay thế »
Dolmen

17

Nếu bạn có một công cụ regex với hỗ trợ Unicode tốt, thì việc khử trùng loại chuỗi này là điều không cần thiết. Ví dụ: trong Perl, bạn có thể xóa tất cả trừ dấu kết hợp đầu tiên khỏi mọi ký tự (do người dùng cảm nhận) như sau:

#!/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");

Điều này sẽ in:

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


9
Tôi không thể đọc tiếng Tây Tạng, nhưng tôi lo ngại rằng cách tiếp cận thô bạo này có thể loại bỏ chức năng khỏi cách ngôn ngữ được thiết kế. Tôi đã thấy unicode có các trường hợp sử dụng hợp pháp của nhiều hơn một dấu kết hợp. Tiếng Ả Rập là một ví dụ điển hình. Tôi sẽ cố gắng nhớ để điều hành điều này bởi các đồng nghiệp Tây Tạng của tôi.
FlipMcF

2
Bạn nói đúng, chắc chắn có những trường hợp nhiều dấu kết hợp là hợp pháp. Nhưng bạn có thể dễ dàng thay đổi regex để cho phép một số điểm tối đa nhất định.
nwellnhof

Được ủng hộ vì nó trả lời câu hỏi 'làm thế nào để bạn làm sạch nó'. Nhưng tôi nghĩ đây sẽ là một cơn ác mộng bảo trì.
FlipMcF

Ngoài ra, RE chỉ loại bỏ sự trùng lặp liền kề . Nó sẽ không dọn dẹp, nói: <base><macron><overline><macron><overline>.... Vì vậy, nếu văn bản của bạn cần nhiều ký tự kết hợp khác nhau , nó sẽ tốt; và văn bản độc hại vẫn có thể được tạo.
Jesse Chisholm

13

"Làm thế nào chúng ta có thể khử trùng điều này" được trả lời tốt nhất ở trên bởi TJ Crowder

Tuy nhiên, tôi nghĩ rằng sanitization là một cách tiếp cận sai và Cristy đã làm đúng với overflow:hiddenphần tử chứa css.

Ít nhất, đó là cách tôi đang giải quyết nó.


6

Ok, điều này khiến tôi mất một lúc để tìm ra, tôi có ấn tượng rằng việc kết hợp các ký tự để tạo ra zalgo bị giới hạn ở những thứ này . Vì vậy, tôi mong đợi theo dõi regex để bắt những con quái vật.

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

và nó không hoạt động ...

Điều đáng chú ý là danh sách trong wiki không bao gồm đầy đủ các ký tự kết hợp.

Điều đã gợi ý cho tôi là "ก้้้้้้้้้้้้้้้้้้้้".charCodeAt(2).toString(16)= "e49" mà không nằm trong phạm vi kết hợp, nó rơi vào "Sử dụng cá nhân".

Trong C #, chúng nằm dưới UnicodeCategory.NonSpacingMarkvà tập lệnh sau sẽ loại bỏ chúng:

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

Bằng cách nhìn vào bảng được tạo, bạn sẽ có thể biết cái nào xếp chồng lên nhau. Một phạm vi bị thiếu trên wiki là 06D6-06DCmột phạm vi khác 0730-0749.

CẬP NHẬT:

Đây là regex được cập nhật sẽ đánh bắt tất cả các zalgo bao gồm cả những con bị bỏ qua trong phạm vi 'bình thường'.

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

Điều khó nhất là xác định chúng, một khi bạn đã làm được điều đó - có vô số giải pháp bao gồm một số giải pháp tốt ở trên.

Hy vọng điều này giúp bạn tiết kiệm thời gian.


Tôi sẽ nói, không để spam thư rác này!
Praveen Kumar Purushothaman

@PraveenKumar Bạn có muốn giải thích thêm ý của bạn không?
Matas Vaitkevicius,

Tôi đánh giá cao câu trả lời của bạn, nhưng đây là một câu hỏi đã trả lời bị mất. Vậy tại sao phải thêm câu trả lời mới một cách không cần thiết? Đó chỉ là quan điểm của tôi. Hơn nữa, câu trả lời của bạn không phải là JavaScript, phải không?
Praveen Kumar Purushothaman

4
@PraveenKumar Nó khám phá ra lý do tại sao xác thực zalgo bình thường ([\u0300–\u036F\u1AB0–\u1AFF\u1DC0–\u1DFF\u20D0–\u20FF\uFE20–\uFE2F]{2,})không hoạt động. Bạn có thấy thú vị khi xếp chồng unicode không giới hạn trên wiki không? Bạn có nghĩa là gì bởi 'câu hỏi đã trả lời bị mất'? CHỈNH SỬA : Bạn có thể thấy kỳ lạ khi thêm câu trả lời cho câu hỏi 3 tuổi, nhưng vì tôi đã mất một lúc để tìm ra lý do tại sao loại hợp tử này hoạt động nên tôi không thể để những kiến ​​thức như vậy lãng phí. Tiếp theo anh chàng sẽ tiết kiệm thời gian.
Matas Vaitkevicius

7
@PraveenKumar câu hỏi không nêu ngôn ngữ và việc đăng câu trả lời mới cho một câu hỏi cũ là hoàn toàn phù hợp nếu các câu trả lời cũ bị thiếu theo một cách nào đó. Rất tiếc, tôi không có đủ kinh nghiệm về vấn đề này, nếu không nó sẽ nhận được sự ủng hộ từ tôi.
Mark Ransom
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.