เกิดอะไรขึ้นกับอักขระที่รวม Unicode เหล่านี้และเราจะกรองได้อย่างไร


92

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

สิ่งเหล่านี้เพิ่งปรากฏในส่วนความคิดเห็นของ Facebook

เราจะฆ่าเชื้อนี้ได้อย่างไร?


5
คุณไม่เคยถามคำถามนี้มาก่อนหรือ? (คำถามที่ตรงไปตรงมา)
Ry-

5
สิ่งเหล่านี้ไม่ใช่ ascii อย่างแน่นอน
Chris Eberle

31
ทำไมต้องปิดโหวต? เป็นคำถามเกี่ยวกับการเขียนโปรแกรมเนื่องจากฉันต้องการทราบวิธีทำความสะอาดข้อมูลประเภทนี้ดังนั้นส่วนความคิดเห็นในเว็บไซต์ของฉันจะไม่เป็นสนามเด็กเล่นของเด็กอายุ 13 ปี ...
XCS

19
กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้ก็็็็็็็็็็็็็็็็็็็็ก็็็็็็็็็็็็็็็็็็็็กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้ก็็็็็็็็็็็็็็็็็็็็กิิิิิิิิิิิิิิิิิิิิ ก้้้้้้้้้้้้้้้้้้้้กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้ก็็็็็็็็็็็็็็็็็็็็ก็็็็็็็็็็็็็็็็็็็็กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้ก็็็็็็็็็็็็็็็็็็็็กิิิิิิิิิิิิิิิ "เพื่อแสดงความคิดเห็นส่วนในเว็บไซต์ของฉันจะไม่เป็น 13 ปีเก่าของสนามเด็กเล่น." จริงๆแล้วหากไม่มีการฆ่าเชื้อการโพสต์อักขระเหล่านี้อาจทำให้ความคิดเห็นด้านบนอ่านไม่ได้ซึ่งไม่ใช่ประสบการณ์ของผู้ใช้ที่พึงพอใจเลย
XCS

14
@pjotr มันไม่ใช่ข้อผิดพลาดของเบราว์เซอร์แน่นอน หากคุณต้องการไม่ให้ตัวละครล้นกล่องที่มีคุณสามารถแก้ได้ด้วย CSS (overflow: hidden;) ...
XCS

คำตอบ:


81

เกิดอะไรขึ้นกับอักขระ Unicode เหล่านี้?

นั่นคือตัวละครที่มีชุดตัวละครรวมกัน เนื่องจากอักขระที่รวมเข้าด้วยกันต้องการอยู่เหนืออักขระพื้นฐานจึงซ้อนกัน (ตามตัวอักษร) ตัวอย่างเช่นกรณีของ

กุ้งเง้ง

... มันคือก (ตัวอักษรไทยko kai ) ( U + 0E01 ) ตามด้วยตัวอักษรไทยรวมmai tho ( U + 0E49 ) จำนวน 20 ชุด

เราจะฆ่าเชื้อนี้ได้อย่างไร?

คุณสามารถประมวลผลข้อความล่วงหน้าและ จำกัด จำนวนอักขระรวมที่สามารถนำไปใช้กับอักขระตัวเดียวได้ แต่ความพยายามนั้นอาจไม่คุ้มกับรางวัล คุณต้องใช้แผ่นข้อมูลสำหรับอักขระปัจจุบันทั้งหมดเพื่อที่คุณจะได้ทราบว่าพวกเขารวมกันหรืออะไรและคุณต้องแน่ใจว่าได้อนุญาตอย่างน้อยสองสามตัวเนื่องจากบางภาษาเขียนด้วยตัวกำกับเสียงหลายตัวในฐานเดียว . ตอนนี้หากคุณต้องการ จำกัด ความคิดเห็นไว้ที่ชุดอักขระละตินนั่นจะเป็นการตรวจสอบช่วงที่ง่ายกว่า แต่แน่นอนว่าเป็นเพียงตัวเลือกหากคุณต้องการ จำกัด ความคิดเห็นไว้เพียงไม่กี่ภาษา ข้อมูลเพิ่มเติมแผ่นรหัส ฯลฯ ที่unicode.org

BTW ถ้าคุณอยากรู้ว่าตัวละครบางตัวถูกสร้างขึ้นอย่างไรสำหรับคำถามอื่นเมื่อเร็ว ๆ นี้ฉันได้เขียนโค้ดหน้า"Unicode Show Me" ที่รวดเร็วและสกปรกบน JSBin คุณเพียงแค่คัดลอกและวางข้อความลงในพื้นที่ข้อความจากนั้นจะแสดงจุดรหัสทั้งหมด (~ อักขระ) ที่ข้อความนั้นประกอบขึ้นด้วยลิงก์เช่นด้านบนไปยังหน้าที่อธิบายอักขระแต่ละตัว ใช้งานได้เฉพาะกับจุดรหัสในช่วง U + FFFF และต่ำกว่าเนื่องจากเขียนด้วย JavaScript และเพื่อจัดการกับอักขระที่อยู่เหนือ U + FFFF ใน JavaScript คุณต้องทำงานมากกว่าที่ฉันต้องการทำสำหรับคำถามนั้น (เนื่องจากใน JavaScript a "character" อยู่เสมอ 16 บิตซึ่งหมายความว่าสำหรับบางภาษาอักขระสามารถแบ่งออกเป็น "อักขระ" JavaScript สองตัวที่แยกจากกันและฉันไม่ได้ระบุไว้) แต่มันมีประโยชน์สำหรับข้อความส่วนใหญ่ ...


1
คุณจะไม่เพียงแค่ลบสำเนาซ้ำ ๆ ของจุดรหัสที่รวมกันกลับไปเป็นสำเนาเดียวหรือไม่? เมื่อใดที่คุณจำเป็นต้องรวมจุดรหัสเดียวกันเข้ากับจุดรหัสฐานมากกว่าหนึ่งครั้ง
Remy Lebeau

4
@RemyLebeau: "เมื่อไหร่ที่คุณจะต้องรวมจุดรหัสเดียวกันเข้ากับจุดรหัสพื้นฐานมากกว่าหนึ่งครั้ง" ฉันไม่รู้ฉันรู้น้อยมากเกี่ยวกับวิธีที่คุณเขียนภาษาอื่นเช่นภาษาไทย ฉันไม่แปลกใจเลยที่พบว่ามีจุดรหัสเดียวกันมากกว่าหนึ่งจุดในบางจุด แต่การทำเช่นนั้นไม่ได้ลดความซับซ้อน คุณยังต้องการตาราง Unicode อย่างใดอย่างหนึ่งเพื่อดูว่าตารางใดกำลังรวมอักขระ
TJ Crowder

ฉันทำให้เพจของคุณยอมรับสตริง Unicode จาก url เช่นjsbin.com/erajer/7/…
ubershmekel

2
ไลบรารี JavaScript เพื่อลบเครื่องหมายรวม Unicode จากสตริงได้อย่างง่ายดาย: mths.be/stripcombiningmarks
Mathias Bynens

JavaScript ใช้ UTF-16 กับ« คู่ตัวแทน »
dolmen

17

หากคุณมีเอนจิ้น regex ที่รองรับ 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

โหวตเพิ่มขึ้นเนื่องจากตอบคำถาม 'วิธีล้างข้อมูลนี้' แต่ฉันคิดว่านี่คงเป็นฝันร้ายของการบำรุงรักษา
FlipMcF

นอกจากนี้ RE ยังลบการทำซ้ำที่อยู่ติดกัน มันจะไม่สะอาดพูด: <base><macron><overline><macron><overline>.... ดังนั้นหากข้อความของคุณต้องการอักขระรวมที่แตกต่างกันหลายตัวก็จะผ่านไปได้ด้วยดี และยังสามารถสร้างข้อความที่เป็นอันตรายได้
Jesse Chisholm

13

"เราจะฆ่าเชื้อสิ่งนี้ได้อย่างไร" TJ Crowderตอบได้ดีที่สุด

อย่างไรก็ตามฉันคิดว่าการฆ่าเชื้อเป็นแนวทางที่ไม่ถูกต้องและคริสตี้ ทำถูกต้องกับoverflow:hiddenองค์ประกอบที่มี css

อย่างน้อยนั่นคือวิธีที่ฉันกำลังแก้ปัญหา


6

ตกลงคนนี้เอาฉันในขณะที่จะคิดออกผมก็รู้สึกว่าการรวมตัวละครในการผลิต zalgo จะจำกัด เหล่านี้ ดังนั้นฉันจึงคาดว่าจะติดตาม regexเพื่อจับคนประหลาด

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

และมันไม่ได้ผล ...

สิ่งที่จับได้คือรายการในวิกิไม่ครอบคลุมอักขระที่รวมกันทั้งหมด

สิ่งที่ทำให้ฉันมีคำใบ้คือ"ก้้้้้้้้้้้้้้้้้้้้".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-06DC0730-0749

อัพเดท:

นี่คือ regex ที่อัปเดตซึ่งควรกำจัด 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.