почему модуль re python2 не может идентифицировать символ u'® '

1

Я получил строку, и я хочу, чтобы re.sub эту строку в Python2, поэтому я попробовал следующий оператор, он работал

>>> import re
>>> re.sub(u"[]", "", u"abc")
'abc'

Но когда я попробовал следующий оператор, он просто не удался как для Windows 10 (Python 2.7.15 | Anaconda, Inc. | (по умолчанию, 1 мая 2018, 18:37:09) [MSC v.1500 64 бит (AMD64)] на win32).

>>> re.sub(ur"[\u2122\u00ae]", "", u"abc")
u'a?b?c'

Я пробовал решение из Python и регулярного выражения с помощью Unicode, но он не работал ни с одним из них.

>>> myre = re.compile(ur'[\u2122\u00ae]', re.UNICODE)
>>> print myre.sub('', u"abc")

Так почему это происходит и как я могу это исправить?

  • 0
    Это не ваша проблема, но вы действительно не должны пытаться u"ab®c" 8-битную строку "" в строку Unicode u"ab®c" . Чтобы сделать это, Python должен угадать, хотите ли вы кодировать один или декодировать другой, и, даже если это окажется правильным, вы все еще полагаетесь на что-то неочевидное и делаете свой код немного медленнее, без веской причины.
  • 0
    @abarnert Да, ты прав, я должен u'' использовать
Показать ещё 7 комментариев
Теги:
python-2.7
python-unicode

2 ответа

4
Лучший ответ

У вас здесь две проблемы.


Во-первых, весь смысл строковых литералов-строк заключается в том, что они не рассматривают escape-обратные экраны как escape-обратные следы. Итак, ur"[\u2122\u00ae]" буквально являются символами [, \, u, 2, 1 и т.д.

В Python 3 это прекрасно, потому что модуль re понимает \u escape-символы, что означает символы Unicode, поэтому шаблон заканчивается тем, что он является символьным классом с U+2122 и U+00AE в нем, точно так, как вы хотите. Но в Python 2 это не так, поэтому класс персонажей оказывается бесполезным бесполезным барахлом.

Если вы измените его, чтобы использовать u"[\u2122\u00ae]" строковый литерал, это решит эту проблему: u"[\u2122\u00ae]". Конечно, это вызовет все другие потенциальные проблемы, из-за которых люди хотят использовать сырые строковые литералы, в первую очередь с регулярными выражениями, но, к счастью, у вас их нет.


Вторая проблема заключается в том, что вы используете символы Unicode в литералах Unicode без объявления кодировки. Опять же, не проблема в Python 3, но она находится в Python 2.

Когда вы вводите "abc", есть хороший шанс, что вы на самом деле не \u2122 Python не \u2122, а \u0099. Вероятно, ваша консоль похожа на cp1252, поэтому, когда вы вводите или вставляете a , то, что на самом деле дает Python, это U + 0099, а не U + 2122. Конечно, ваша консоль также неправильно отображает вещи, так что U+0099 заканчивается так же, как и . Но Python не знает, что происходит. Он просто видит, что U + 0099 не тот же символ, что и U + 2122, и поэтому нет совпадения. (Ваш первый пример работает, потому что ваша строка поиска также имеет неправильный \u0099, так что это происходит, чтобы соответствовать.)

В исходном коде вы можете исправить это, добавив объявление кодировки, чтобы сообщить Python, что вы используете cp1252, или указав редактору использовать UTF-8 вместо cp1252. Но в интерактивном интерпретаторе вы получаете любую кодировку, требуемую вашей консолью, и негде было бы поместить объявление кодирования.

На самом деле нет хорошего решения.

Ну, есть: обновление до Python 3. Основная причина, по которой он существует, заключается в том, чтобы сделать головные боли Unicode такими, как это происходит, и Python 2 меньше, чем полтора года с конца жизни, так что вы действительно хотите узнать, как бороться с головными болями Юникода в Python 2 сегодня?

Вы также можете получить терминал UTF-8 (и тот, который Python распознает как таковой). Это автоматическое определение на macOS или последних Linux-дистрибутивах; на Windows это намного сложнее, и, вероятно, не так, как вы хотите пойти сюда.

Таким образом, единственной альтернативой является просто никогда не использовать символы Unicode в литералах Unicode в интерактивном интерпретаторе. Опять же, вы можете использовать их в исходном коде, но в интерактивном режиме вы должны:

  • Используйте обратную косую черту.
  • Используйте литералы, отличные от Unicode, и тщательно их расшифровывайте.

Я не уверен, действительно ли "abc".decode('cp1252') лучше, чем \u экранов, но он будет работать.

  • 0
    Согласно вашему предложению, я использовал их в исходном коде, и это прекрасно работает с использованием Unicode. Тем временем я обновляю регулярное выражение для u"[\u0099\u2122]" чтобы посмотреть, сможет ли Python идентифицировать метку если консоль u"[\u0099\u2122]" некоторую неверную интерпретацию, и в результате будет показано, что Python по-прежнему не может соответствовать, возможно, это потому, что моя консоль по умолчанию это ANSI? В целом, я думаю, что вы правы, использование Python 2 является самой проблемой.
0

Просто удалите r перед строкой, и она работает:

re.sub(u"[\u2122\u00ae]", "", u"abc")
  • 0
    Я скопировал ваш код, и он все еще не работает на Python 2.7.15 |Anaconda, Inc.| (default, May 1 2018, 18:37:09) [MSC v.1500 64 bit (AMD64)] on win32 . Это печатает u'a?b?c'
  • 0
    @calvin Ваша попытка в этом вопросе и этот ответ работает на моей машине. Я использую Python 2.7.10 и macOS HighSierra. Может быть, что-то делать с кодировкой Windows?
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню