ส่องตัวอักษร
ข้อความที่คัดลอกมาจาก Excel, PDF หรือ LINE บางครั้งมีตัวที่มองไม่เห็นติดมา หน้าตาเหมือนกันทุกอย่าง แต่ค้นหาหรือเทียบแล้วไม่เจอ วางข้อความไว้ที่นี่ แล้วดูทีละตัวว่ามีอะไรซ่อนอยู่
- ตัวที่ตาเห็น
- 48
- Code point
- 61
- .length ใน JS
- 61
- ไบต์
- 166
grapheme
ตัวอักษรใน Unicode
หน่วย UTF-16
UTF-8 แบบที่ strlen() ของ PHP นับ
ปัญหาที่พบ
ตัวที่มองไม่เห็น1 จุด
zero-width space, ZWNJ, ZWJ, word joiner, BOM, soft hyphen หรือตัวขึ้นบรรทัดแบบพิเศษ ตาไม่เห็นแต่โปรแกรมนับเป็นตัวอักษร ค้นหาหรือเทียบข้อความจึงไม่เจอ
ช่องว่างที่ไม่ใช่ space ธรรมดา1 จุด
NBSP (U+00A0) และช่องว่างแบบอื่นหน้าตาเหมือน space แต่เป็นคนละตัว trim() ของ PHP ไม่ตัดออก และแยกคำด้วย space ก็ไม่แยกตรงนี้
สระเอสองตัวแทนสระแอ1 จุด
เเ (U+0E40 สองครั้ง) หน้าตาเหมือน แ (U+0E41) แต่ค้นคำว่า แม่ จะไม่เจอ มักมาจากความเคยชินตอนพิมพ์ หรือข้อความที่ดึงมาจาก PDF
สระอำที่พิมพ์เป็นสองตัว1 จุด
สระอำที่ถูกคือตัวเดียว (U+0E33) แต่บางข้อความมาเป็นนิคหิตกับสระอา (U+0E4D U+0E32) ซึ่งแสดงผลเหมือนกัน คำว่า น้ำ ในข้อความนี้จึงค้นไม่เจอ
วรรณยุกต์มาก่อนสระ1 จุด
ลำดับที่ถูกคือพยัญชนะ สระบนหรือสระล่าง แล้วจึงวรรณยุกต์ ถ้าพิมพ์ไม้เอกก่อนสระอี หลายฟอนต์ยังแสดงเหมือน กี่ แต่ข้อมูลเป็นคนละชุดกัน
เลขไทยปนเลขอารบิก1 จุด
ข้อความเดียวมีทั้ง ๐–๙ และ 0–9 เช่นเบอร์โทรที่พิมพ์ปนกัน validation ที่รับเฉพาะ 0–9 จะไม่ผ่าน และค้นหาหรือเรียงลำดับผิด
ถ้าใช้แค่ NFC
หลัง NFC ยังเหลือปัญหา 6 จาก 6 จุด
NFC ไม่เปลี่ยน เเ เป็น แ ไม่รวมนิคหิตกับสระอาเป็นสระอำ ไม่ลบตัวที่มองไม่เห็น และสลับวรรณยุกต์ให้เฉพาะกับสระล่าง ส่วน NFKC กลับแยกสระอำออกเป็นสองตัว
ตรวจในเบราว์เซอร์นี้ ข้อความไม่ได้ส่งไปที่ไหน
ทีละตัวอักษร
หนึ่งช่องคือหนึ่งตัวที่ตาเห็น (grapheme) ใต้ตัวอักษรคือ code point ที่ประกอบกันอยู่
- เ
- U+0E40SARA Eสระเอ
- เ
- U+0E40SARA Eสระเอ
- จ้
- U+0E08CHO CHANจ จาน
- U+0E49MAI THOไม้โท
- ง
- U+0E07NGO NGUง งู
- โ
- U+0E42SARA Oสระโอ
- อ
- U+0E2DO ANGอ อ่าง
- น
- U+0E19NO NUน หนู
- แ
- U+0E41SARA AEสระแอ
- ล้
- U+0E25LO LINGล ลิง
- U+0E49MAI THOไม้โท
- ว
- U+0E27WO WAENว แหวน
- ค่
- U+0E04KHO KHWAIค ควาย
- U+0E48MAI EKไม้เอก
- ะ
- U+0E30SARA Aสระอะ
- NBSP
- U+00A0NO-BREAK SPACE
- ย
- U+0E22YO YAKย ยักษ์
- อ
- U+0E2DO ANGอ อ่าง
- ด
- U+0E14DO DEKด เด็ก
- ·
- U+0020SPACE
- ๑
- U+0E51DIGIT ONEเลขไทย ๑
- ,
- U+002CCOMMA
- 2
- U+0032DIGIT 2
- 5
- U+0035DIGIT 5
- 0
- U+0030DIGIT 0
- ·
- U+0020SPACE
- บ
- U+0E1ABO BAIMAIบ ใบไม้
- า
- U+0E32SARA AAสระอา
- ท
- U+0E17THO THAHANท ทหาร
- ZWSP
- U+200BZERO WIDTH SPACE
- ↵
- U+000ALINE FEED
- ค่
- U+0E04KHO KHWAIค ควาย
- U+0E48MAI EKไม้เอก
- า
- U+0E32SARA AAสระอา
- น้ํ
- U+0E19NO NUน หนู
- U+0E49MAI THOไม้โท
- U+0E4DNIKHAHITนิคหิต
- า
- U+0E32SARA AAสระอา
- เ
- U+0E40SARA Eสระเอ
- ดื
- U+0E14DO DEKด เด็ก
- U+0E37SARA UEEสระอือ
- อ
- U+0E2DO ANGอ อ่าง
- น
- U+0E19NO NUน หนู
- นี้
- U+0E19NO NUน หนู
- U+0E35SARA IIสระอี
- U+0E49MAI THOไม้โท
- ·
- U+0020SPACE
- ส่
- U+0E2ASO SUAส เสือ
- U+0E48MAI EKไม้เอก
- ง
- U+0E07NGO NGUง งู
- ไ
- U+0E44SARA AI MAIMALAIสระไอ ไม้มลาย
- ด้
- U+0E14DO DEKด เด็ก
- U+0E49MAI THOไม้โท
- ก่ี
- U+0E01KO KAIก ไก่
- U+0E48MAI EKไม้เอก
- U+0E35SARA IIสระอี
- โ
- U+0E42SARA Oสระโอ
- ม
- U+0E21MO MAม ม้า
- ง
- U+0E07NGO NGUง งู
- ค
- U+0E04KHO KHWAIค ควาย
- ะ
- U+0E30SARA Aสระอะ
ตัวที่มองไม่เห็นที่เจอบ่อย
โปรแกรมเทียบข้อความทีละ code point ไม่ได้ดูหน้าตา ตัวเหล่านี้จึงทำให้ข้อความสองชุดที่ดูเหมือนกัน ไม่เท่ากัน
| Code point | ชื่อ | มักติดมากับ |
|---|---|---|
| U+200B | Zero width space | หน้าเว็บที่ใส่ไว้บอกจุดตัดคำภาษาไทย |
| U+00A0 | No-break space | Excel, Word และ ในหน้าเว็บ |
| U+FEFF | BOM | ต้นไฟล์ CSV ที่บันทึกจาก Excel แบบ UTF-8 |
| U+00AD | Soft hyphen | Word และ PDF ที่ตัดคำท้ายบรรทัด |
| U+200C, U+200D | ZWNJ, ZWJ | ใช้ต่ออีโมจิ หลุดมาเดี่ยว ๆ เมื่อคัดลอกอีโมจิไม่ครบ |
| U+FE0F | Variation selector-16 | ค้างอยู่หลังลบอีโมจิออกไม่หมด |
| U+2028 | Line separator | ข้อความจาก PDF และแอปบางตัว |
ทำความสะอาดก่อนบันทึก
ข้อความที่ผู้ใช้วางเข้ามาในฟอร์ม ควรทำความสะอาดก่อนบันทึกหรือก่อนค้นหา ฟังก์ชันนี้แก้เรื่องหลักแบบเดียวกับหน้านี้ ใน Laravel เรียกได้จาก prepareForValidation() ของ FormRequest
function cleanThai(string $text): string
{
// ตัวที่มองไม่เห็น (เว้น ZWJ ที่ใช้ต่ออีโมจิ) และช่องว่างพิเศษ
$invisible = '/[\x{200B}\x{200C}\x{2060}\x{FEFF}\x{00AD}]/u';
$spaces = '/[\x{00A0}\x{2000}-\x{200A}\x{202F}\x{3000}]/u';
$text = preg_replace([$invisible, $spaces], ['', ' '], $text);
// เเ เป็น แ และนิคหิตกับสระอาเป็นสระอำ
$text = strtr($text, [
"\u{0E40}\u{0E40}" => "\u{0E41}",
"\u{0E4D}\u{0E32}" => "\u{0E33}",
]);
// วรรณยุกต์ที่มาก่อนสระ สลับให้สระมาก่อน
$tone = '[\x{0E48}-\x{0E4B}]';
$vowel = '[\x{0E31}\x{0E34}-\x{0E39}]';
return preg_replace("/($tone)($vowel)/u", '$2$1', $text);
}Normalizer::normalize() แบบ NFC ไม่ช่วยเรื่อง เเ และสระอำ ส่วน trim() ไม่ตัด NBSP และ zero width space ที่หัวท้ายข้อความ
เครื่องมืออื่น
ดูทั้งหมด- สุ่มเลขบัตรประชาชน
เลข 13 หลักที่หลักตรวจสอบถูกตามสูตร ใช้กรอกฟอร์มตอนทดสอบระบบ
- แปลงเลขไทย และจำนวนเงินเป็นคำอ่าน
สลับเลขอารบิกกับเลขไทยทั้งย่อหน้า และเขียนยอดเงินเป็นคำอ่าน ครบทั้งบาท สตางค์ และถ้วน
- สุ่มเลขผู้เสียภาษีนิติบุคคล
เลข 13 หลักของบริษัทและห้างหุ้นส่วนที่หลักตรวจสอบถูกตามสูตร พร้อมตัวตรวจที่แยกความหมายทีละหลัก
- สร้าง QR พร้อมเพย์สำหรับทดสอบ
QR และ payload EMVCo จากเบอร์มือถือ เลขบัตร หรือ e-Wallet ID แยกให้ดูทีละฟิลด์ พร้อม CRC16
- แปลง พ.ศ. ค.ศ. และรูปแบบวันที่ไทย
แปลงปีไปกลับ และลองพิมพ์ format ของ thaidate() ดูผลก่อนใช้จริง
- นับตัวอักษร SMS ภาษาไทย
ดูว่าข้อความไทยหรือมีอีโมจิต้องส่งกี่ SMS เหลือกี่ตัว และแบ่งตรงไหน
- ข้อมูลจังหวัด อำเภอ ตำบล และรหัสไปรษณีย์
รหัสจากกรมการปกครอง รหัสไปรษณีย์จากไปรษณีย์ไทย บอกที่มาทุกแถว ดาวน์โหลดได้ทั้ง JSON CSV SQL และ Excel
- ค้นหาอีโมจิด้วยชื่อภาษาไทย
พิมพ์คำไทยแล้วเจออีโมจิที่ต้องการ หรือวางอีโมจิเพื่อดูชื่อ พร้อม code point และโค้ดสำหรับ HTML JS และ PHP
มีงานอยากให้ช่วย เล่าให้เราฟัง
บอกสั้น ๆ ว่าอยากทำอะไร หรือระบบเดิมติดตรงไหน เดี๋ยวเราติดต่อกลับทางที่คุณสะดวก
หรืออีเมลถึงเราโดยตรง [email protected]