PYTHON RE Не разделяйте символы Юникода на суррогатные пары при сопоставлении

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

Смотрите следующий пример:

Как это сейчас:

$ te = u'\U0001f600\U0001f600'
$ flags1 = regex.findall(".", te, re.UNICODE)
$ flags1
>>> [u'\ud83d', u'\ude00', u'\ud83d', u'\ude00']

Мое желание:

$ te = u'\U0001f600\U0001f600'
$ flags1 = regex.findall(".", te, re.UNICODE)
$ flags1
>>> [u'\U0001f600', u'\U0001f600']

Зачем мне это на самом деле нужно, потому что я хочу перебирать строку Юникода и получать каждую итерацию следующим символом Юникода.

Смотрите пример:

for char in  regex.findall(".", te, re.UNICODE):
   print char

Спасибо заранее =)

1 ответ

Решение

Используйте регулярное выражение, которое соответствует суррогатной паре или чему-либо еще. Это будет работать в широких и узких сборках Python 2, но не требуется в широкой сборке, поскольку в нем не используются суррогатные пары.

Python 2.7.14 (v2.7.14:84471935ed, Sep 16 2017, 20:19:30) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import re
>>> te = u'A\u5200\U0001f600\U0001f601\u5100Z'
>>> print re.findall(ur'[\ud800-\udbff][\udc00-\udfff]|.', te, re.UNICODE)
[u'A', u'\u5200', u'\U0001f600', u'\U0001f601', u'\u5100', u'Z']

Это все еще будет работать в последней версии Python 3, но также не нужно, потому что суррогатные пары больше не используются в строках Unicode (больше не используется широкая или узкая сборка):

Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:59:51) [MSC v.1914 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import re
>>> te = u'A\u5200\U0001f600\U0001f601\u5100Z'
>>> print(re.findall(r'[\ud800-\udbff][\udc00-\udfff]|.', te))
['A', '刀', '', '', '儀', 'Z']

Работает без суррогатного матча:

>>> print(re.findall(r'.', te))
['A', '刀', '', '', '儀', 'Z']

И тогда вы можете просто повторить в Python 3:

>>> for c in te:
...     print(c)
...
A
刀


儀
Z

Обратите внимание, что проблема с графемами сохраняется (комбинации кодовых точек Unicode, представляющие один символ. Вот плохой случай:

>>> s = '‍‍‍'
>>> for c in s:
...     print(c)
...     


‍


‍


‍


regex Сторонний модуль может соответствовать графам:

>>> import regex
>>> s = '‍‍‍'
>>> for c in regex.findall('\X',s):
...     print(c)
...     
‍‍‍
Другие вопросы по тегам