การค้นหาแถวที่ไม่ใช่ ASCII จาก Postgres


14

ไม่[:ascii:]ทำงานในระดับ Postgres ที่ทั้งหมดหรือไม่ มันไม่ได้ระบุไว้ในความช่วยเหลือของพวกเขาแต่ฉันเห็นตัวอย่างในเว็บที่ใช้มัน

ฉันมีฐานข้อมูล UTF-8 โดยมีการเปรียบเทียบและc_typ e en_US.UTF-8และรุ่น Postgres คือ 9.6.2 เมื่อฉันค้นหาแถวที่ไม่ใช่ ASCII เช่นนี้:

select title from wallabag_entry where title ~ '[^[:ascii:]]';

ฉันจะได้รับทั้ง Unicode และไม่ใช่ Unicode สัญลักษณ์ (เอาท์พุทเต็มรูปแบบที่นี่ ):

Сталинская правозащитница: мать Меленкова бабушка Настя
Дневник НКВДиста Шабалина: Знает ли Москва положение на фронте?
Бег по городу и поездка на осле: как в средневековье наказывали прелюбодеев
Как комиссар Крекшин в 1740 чуть не отменил историю России
Have you heard of Saint Death? Dont pray to her.
Архаїчна українська мова: перевага чи недолік?
Гренада не их
Chinas marriage rate is plummeting because women are choosing autonomy over 

เกิดอะไรขึ้นกับแบบสอบถามนี้


1
เป็นไปได้ไหมว่าคุณได้รับประโยคที่มีช่องว่างแบบ Unicode ที่ไม่แตกหักง่าย? (หรือตัวละครอื่น ๆ ที่ซ่อนอยู่ในมุมมองธรรมดาสำหรับเรื่องนั้น)
joanolo

@joanolo วิธีตรวจสอบนี้ วิธีดูมุมมองที่ไม่ธรรมดา
Suncatcher

คุณสามารถใช้ a regexp_replace()เพื่อทำเครื่องหมายตัวอักษรที่ไม่ใช่ ASCII ของคุณ ดูคำตอบของฉัน
joanolo

1
คุณควรวางผลลัพธ์ที่แน่นอนใน dba.se เสมอ เราไม่สามารถทดสอบกราฟิกสำหรับอักขระที่ไม่ใช่ ASCII เราสามารถทดสอบชุดผลลัพธ์ที่แท้จริง นี่เป็นเด็กโปสเตอร์ที่ไม่ควรเป็นกราฟิก
Evan Carroll

2
เพียงเพื่อเพิ่มสองเซ็นต์ของฉัน: ในขณะที่คำตอบของโจแอนโนโลนั้นงดงาม แต่ก็ไม่ได้ช่วยฉันในการแก้ปัญหาที่เป็นรูปธรรมนี้ ยกเว้นคำพูดที่เหมาะสมชุดข้อมูลที่ฉันมีพวงของตัวละครอื่น ๆ ทำให้เกิดความสับสน (พื้นที่เหมือนกัน"«) ซึ่งจะทำให้มันเป็นไปไม่ได้ที่จะใช้[:ascii:]ระดับต่อไป. จริงๆสิ่งที่ช่วยผมในปัญหานี้เป็นแนวคิดของบล็อก Unicode ซึ่งผมได้เรียนรู้จากregex เหลือเชื่อนี้ กวดวิชา .
Suncatcher

คำตอบ:


25

เพื่อตอบคำถามของคุณ: [:ascii:]ทำงาน คุณอาจมีตัวละครบางตัวในข้อความของคุณซึ่งคุณไม่รู้จักว่าไม่ใช่ ASCIIแต่มีอยู่ในนั้น พวกเขาสามารถเป็นสิ่งที่ต้องการไม่ใช่พื้นที่เปราะบางเช่นหรืออื่น ๆอักขระ Unicode พื้นที่

ไม่แปลกที่จะมีช่องว่างที่ไม่สามารถแตกหักได้ (  ) ในข้อความที่คุณคัดลอกและวางจากหน้าเว็บ แต่คุณไม่สังเกตเห็นว่ามีอยู่

นี่คือตัวอย่างที่จะแสดง:

WITH t(t) AS
(
    VALUES 
      ( 'Сталинская правозащитница: мать Меленкова бабушка Настя' ),
      ( 'Дневник НКВДиста Шабалина: Знает ли Москва положение на фронте?' ),
      ( 'Бег по городу и поездка на осле: как в средневековье наказывали прелюбодеев' ),
      ( 'Как комиссар Крекшин в 1740-е чуть не отменил историю России' ),
      ( 'Have you heard of Saint Death? Don’t pray to her.' ),
      ( 'Архаїчна українська мова: перевага чи недолік?' ),
      ( 'Гренада не их' ),
      ( 'China’s marriage rate is plummeting because women are choosing autonomy over ' )

)
SELECT 
    t,  regexp_replace(t, '([^[:ascii:]])', '[\1]', 'g') AS t_marked
FROM 
    t 
WHERE 
    t ~ '[^[:ascii:]]' ;

นั่นคือสิ่งที่คุณได้รับ:

                                       t                                       |                                                                                                 t_marked                                                                                                  
-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Сталинская правозащитница: мать Меленкова бабушка Настя                       | [С][т][а][л][и][н][с][к][а][я] [п][р][а][в][о][з][а][щ][и][т][н][и][ц][а]: [м][а][т][ь] [М][е][л][е][н][к][о][в][а] [б][а][б][у][ш][к][а] [Н][а][с][т][я]
 Дневник НКВДиста Шабалина: Знает ли Москва положение на фронте?               | [Д][н][е][в][н][и][к] [Н][К][В][Д][и][с][т][а] [Ш][а][б][а][л][и][н][а]: [З][н][а][е][т] [л][и] [М][о][с][к][в][а] [п][о][л][о][ж][е][н][и][е] [н][а] [ф][р][о][н][т][е]?
 Бег по городу и поездка на осле: как в средневековье наказывали прелюбодеев   | [Б][е][г] [п][о] [г][о][р][о][д][у] [и] [п][о][е][з][д][к][а] [н][а] [о][с][л][е]: [к][а][к] [в] [с][р][е][д][н][е][в][е][к][о][в][ь][е] [н][а][к][а][з][ы][в][а][л][и] [п][р][е][л][ю][б][о][д][е][е][в]
 Как комиссар Крекшин в 1740 чуть не отменил историю России                  | [К][а][к] [к][о][м][и][с][с][а][р] [К][р][е][к][ш][и][н] [в] 1740-[е] [ч][у][т][ь] [н][е] [о][т][м][е][н][и][л] [и][с][т][о][р][и][ю] [Р][о][с][с][и][и]
 Have you heard of Saint Death? Dont pray to her.                             | Have you heard of Saint Death? Don[’]t pray to her.
 Архаїчна українська мова: перевага чи недолік?                                | [А][р][х][а][ї][ч][н][а] [у][к][р][а][ї][н][с][ь][к][а] [м][о][в][а]: [п][е][р][е][в][а][г][а] [ч][и] [н][е][д][о][л][і][к]?
 Гренада не их                                                                 | [Г][р][е][н][а][д][а] [н][е] [и][х]
 Chinas marriage rate is plummeting because women are choosing autonomy over  | China[’]s marriage rate is plummeting because women are choosing autonomy over 

คุณสามารถเห็นได้จากสิ่งนี้ว่าปัญหาของคุณคือตัวละครอะโพสโทรฟีที่ถูกต้อง ASCII รองรับเครื่องหมายอะโพสโทรฟีเท่านั้น อะโพสโทรฟีซ้ายและอะพอสโทรฟีด้านขวาเป็นส่วนขยาย Unicode ที่ถูกต้องในการพิมพ์

dbfiddle ที่นี่

คุณสามารถตรวจสอบกับรุ่นก่อนหน้าได้ที่http://rextester.com/UKIQ48014 (PostgreSQL 9.5) และhttp://sqlfiddle.com/#!15/4c563/1/0 (PostgreSQL 9.3)


ข้อความที่ฉันคิดว่าคุณคิดว่าเป็น ASCII แท้ๆและไม่ใช่ :

 WITH t(t) AS
 (
     VALUES 
       ('A fully ASCII text!'),
       ('Have you heard of Saint Death? Don’t pray to her.'),
       ('China’s marriage rate is plummeting because women are choosing autonomy over ')
 )
 SELECT 
    regexp_replace(t, '([^[:ascii:]])', '[\1]', 'g') AS t_marked
 FROM 
    t 
 WHERE 
    t ~ '[^[:ascii:]]' ;
| t_marked |
 | : ------------------------------------------------- ----------------------------- |
 | คุณเคยได้ยินเรื่อง Saint Death หรือไม่? อย่าสวดอ้อนวอนกับเธอ |
 | อัตราการแต่งงานของจีนลดลงเพราะผู้หญิงเลือกอิสระในการ |
 

dbfiddle ที่นี่

ข้อความเหล่านี้ใช้'แทน'เพื่อทำเครื่องหมายเครื่องหมายวรรคตอน

ตรวจสอบเครื่องหมายวรรคตอน: ทำไมเครื่องหมายคำพูดเดี่ยวที่ถูกต้อง (U + 2019) และไม่ใช่เครื่องหมายอัญประกาศเชิงความหมายที่ชัดเจน (U + 0027) อักขระเครื่องหมายอัญประกาศเดี่ยวที่ต้องการใน Unicode ... เพื่อดูว่าคุณไม่ใช่คนแรกที่ประสบปัญหานี้


3
นี่เป็นคำตอบที่วิเศษมากเพราะมันแสดงให้คุณเห็นถึงตัวละครที่ไม่ใช่ ASCII นี่คือวิธีที่ฉันจะตอบคำถามนี้
Evan Carroll

1
ฉันอัปเดตด้วยตัวอย่าง OPs
Evan Carroll

1
คำตอบที่ยอดเยี่ยมและเป็นประโยชน์จริงๆ! ขอบคุณ
Suncatcher
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.