Строка Python Unicode в регулярных выражениях - PullRequest
0 голосов
/ 07 мая 2018

У меня есть исходный файл в кодировке Unicode (с спецификацией) и некоторая строка, содержащая символы Unicode. Я хочу заменить все символы, которые не принадлежат определенному набору символов, подчеркиванием.

#  coding: utf-8 
import os
import sys
import re

t = "? [°]    \n  € dsf $ ¬ 1 Ä 2 t3¥4Ú";
print re.sub(r'[^A-Za-z0-9 !#%&()*+,-./:;<=>?[\]^_{|}~"\'\\]', '_', t, flags=re.UNICODE)

output:     ____ [__]    _  ___ dsf _ __ 1 __ 2 t3__4__
expected:   _ [_]    _  _ dsf _ _ 1 _ 2 t3_4_

Но каждый символ заменяется числом его подчеркиваний, которое может быть равно байту в его представлении в юникоде.

Может быть, дополнительная проблема:

В реальной задаче строки читаются из файла Unicode другим модулем Python, и я не знаю, правильно ли он обрабатывает уникальность. Таким образом, строковая переменная может быть помечена как ascii, но содержит последовательности в юникоде.

Ответы [ 2 ]

0 голосов
/ 07 мая 2018

Работа со строками Юникода, а не со строками байтов. Ваш источник кодируется как UTF-8, поэтому символы кодируются от одного до четырех байтов каждый. Поможет декодирование в строки Unicode или использование констант Unicode. Код также, кажется, основан на Python 2, поэтому в узких сборках Python 2 (по умолчанию в Windows) у вас все еще будет проблема. У вас также могут возникнуть проблемы, если у вас есть графемы, построенные с двумя или более кодами Unicode:

#  coding: utf-8 
import re

t = u"? [°]    \n  € dsf $ ¬ 1 Ä 2 t3¥4Ú";
print re.sub(ur'[^A-Za-z0-9 !#%&()*+,-./:;<=>?[\]^_{|}~"\'\\]', '_', t, flags=re.UNICODE)

Вывод (в узкой сборке Windows Python 2.7):

__ [_]    _  _ dsf _ _ 1 _ 2 t3_4_

Обратите внимание, что у первого смайлика по-прежнему двойное подчеркивание. Символы Unicode, превышающие U + FFFF, кодируются как суррогатные пары. Это можно сделать, явно проверив их. Первая кодовая точка суррогатной пары - от U + D800 до U + DBFF, а вторая - от U + DC00 до U + DFFF:

#  coding: utf-8 
import re

t = u"? [°]    \n  € dsf $ ¬ 1 Ä 2 t3¥4Ú";
print re.sub(ur'[\ud800-\udbff][\udc00-\udfff]|[^A-Za-z0-9 !#%&()*+,-./:;<=>?[\]^_{|}~"\'\\]', '_', t, flags=re.UNICODE)

Выход:

_ [_]    _  _ dsf _ _ 1 _ 2 t3_4_

Но у вас все равно будет проблема со сложными смайликами:

#  coding: utf-8 
import re

t = u"??‍??‍??‍??";
print re.sub(ur'[\ud800-\udbff][\udc00-\udfff]|[^A-Za-z0-9 !#%&()*+,-./:;<=>?[\]^_{|}~"\'\\]', '_', t, flags=re.UNICODE)

Выход:

___________
0 голосов
/ 07 мая 2018

Как насчет:

print(re.sub(r'[^A-Öa-ö0-9 !#%&()*+,-./:;<=>?[\]^_{|}~"\'\\]', '_', t))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...