Truy vấn các hàng không phải ASCII từ Postgres


14

Liệu [:ascii:]công việc lớp trong Postgres ở tất cả? Nó không được liệt kê trong trợ giúp của họ , tuy nhiên tôi thấy các ví dụ trên web sử dụng nó.

Tôi có cơ sở dữ liệu UTF-8, trong đó đối chiếuc_typ e en_US.UTF-8và phiên bản Postgres là 9.6.2. Khi tôi tìm kiếm các hàng không phải ASCII như thế này:

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

Tôi nhận được cả ký hiệu Unicode và không Unicode (đầu ra đầy đủ ở đây ):

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

Điều gì sai với truy vấn này?


1
Có thể là bạn đang nhận được câu với không gian không thể phá vỡ Unicode? (hoặc bất kỳ nhân vật nào khác ẩn trong chế độ xem đơn giản, cho vấn đề đó)
joanolo

@joanolo, làm sao để kiểm tra cái này? Làm thế nào để xem cái nhìn không đơn giản?
Suncatcher

Bạn có thể sử dụng regexp_replace()dấu để đánh dấu các ký tự không phải ASCII của mình. Xem câu trả lời của tôi.
joanolo

1
Bạn phải luôn luôn dán kết quả chính xác trong dba.se. Chúng tôi không thể kiểm tra đồ họa cho các nhân vật không phải là ascii. chúng ta có thể kiểm tra tập kết quả thực tế. Đây là một đứa trẻ không nên là đồ họa
Evan Carroll

2
Chỉ cần thêm hai xu của tôi: trong khi câu trả lời của joanolo thật ngoạn mục, nó không giúp tôi giải quyết vấn đề cụ thể này. Ngoại trừ trích dẫn đúng, tập dữ liệu của tôi có một loạt các ký tự khó hiểu khác (không gian giống nhau, ",«) khiến cho không thể sử dụng [:ascii:]lớp nào. Điều thực sự giúp tôi trong vấn đề này là một khái niệm về các khối unicode, mà tôi đã học được từ regex tuyệt vời này hướng dẫn .
Suncatcher

Câu trả lời:


25

Để trả lời câu hỏi của bạn: [:ascii:] hoạt động. Bạn có thể có một số ký tự trong văn bản mà bạn không nhận ra là không phải ASCII , nhưng chúng vẫn ở đó. Chúng có thể là một cái gì đó giống như một không gian không thể phá vỡ , ví dụ, hoặc bất kỳ ký tự không gian Unicode nào khác .

Không có gì lạ khi có các khoảng trắng không thể phá vỡ (  ) trong các văn bản mà bạn sao chép và dán từ một trang web, nhưng bạn không nhận thấy chúng ở đó.

Dưới đây là một ví dụ để hiển thị:

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:]]' ;

Đó là điều bạn nhận được:

                                       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 

Bạn có thể thấy từ vấn đề này, rằng vấn đề của bạn là nhân vật tông đồ đúng . ASCII chỉ hỗ trợ dấu nháy đơn. Dấu nháy đơn bên trái và dấu nháy đơn phải là các phần mở rộng Unicode chính xác về mặt chữ viết.

dbfiddle ở đây

Bạn cũng có thể kiểm tra nó với các phiên bản trước tại http://rextester.com/UKIQ48014 (PostgreQuery 9.5) và http://sqlfiddle.com/#!15/4c563/1/0 (PostgreQuery 9.3)


Các văn bản mà tôi đoán bạn nghĩ là ASCII thuần túy, và không :

 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:]]' ;
| đánh dấu |
 | : ------------------------------------------------- ----------------------------- |
 | Bạn đã nghe nói về Saint Death chưa? Đừng [cầu nguyện] với cô ấy. |
 | Tỷ lệ kết hôn của Trung Quốc đang giảm mạnh vì phụ nữ đang chọn quyền tự chủ hơn |
 

dbfiddle ở đây

Các văn bản này đang sử dụng ' thay vì ' để đánh dấu dấu nháy đơn.

Kiểm tra dấu câu: Tại sao dấu ngoặc đơn đúng (U + 2019) và không phải dấu nháy đơn riêng biệt về mặt ngữ nghĩa (U + 0027), ký tự dấu nháy đơn ưa thích trong Unicode? ... Để thấy rằng bạn không phải là người đầu tiên gặp phải vấn đề này.


3
Đây là một câu trả lời thực sự tuyệt vời bởi vì nó cho bạn thấy các nhân vật không phải là ascii. Đây là cách tôi sẽ trả lời câu hỏi này.
Evan Carroll

1
Tôi đã cập nhật với ví dụ OP.
Evan Carroll

1
Câu trả lời thực sự tuyệt vời và hữu ích! Cảm ơn.
Suncatcher
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.