Как обнаружить двухбайтовые числа

Я должен проверять строки на японском языке, закодированные двухбайтовыми символами (естественно, файлы не в Unicode, и я должен хранить их в Shift-JIS). Многие из этих строк содержат цифры, которые также являются двухбайтовыми символами (123456789) вместо стандартных однобайтовых цифр (0-9). Таким образом, обычные методы поиска цифр не будут работать (например, с использованием [0-9] в регулярном выражении или \d).

Единственный способ, который я нашел, чтобы заставить его работать, - это создать кортеж и выполнить итерацию по кортежу в строке для поиска совпадения, но есть ли более эффективный способ сделать это?

Это пример вывода, который я получаю при поиске двухбайтовых чисел:

>>> s = "234"  # "2" is a double-byte integer
>>> if u"2" in s:
      print "y"

>>> if u"2" in s:
      print "y"

    y
>>> print s[0]

>>> print s[:2]
    2
>>> print s[:3]
    23

Любой совет будет принят с благодарностью!


person Tensigh    schedule 12.09.2014    source источник
comment
преобразовать строку в unicode, выполнить поиск с помощью регулярного выражения unicode, сделать со строкой все, что вам нужно, преобразовать обратно в shift-jis...   -  person isedev    schedule 12.09.2014
comment
Как уже сказал @isedev, убедитесь, что вы всегда работаете в юникоде в Python (а не в UTF8/16). Затем вы можете использовать модуль unicodedata, чтобы получить информацию о символах, для пример: unicodedata.numeric(u'1') => 1.0 или unicodedata.name(u'1') => 'FULLWIDTH DIGIT ONE' или unicodedata.digit(u'1') => 1   -  person Lukas Graf    schedule 12.09.2014
comment
Я пробовал это раньше, но с ограниченным успехом. Все Shift-JIS могут конвертировать в Unicode, но не наоборот. Я попробую еще раз.   -  person Tensigh    schedule 12.09.2014
comment
@Tensigh Я думаю, вы путаете кодировки Unicode и UTF. Вы не можете вывести Unicode из Python (или любого языка) в файл, сеть, STDOUT и т. д. Вы можете вывести только строку байтов, которую нужно будет закодировать в кодировке, такой как UTF-8.   -  person Lukas Graf    schedule 12.09.2014
comment
@LukasGraf, спасибо, это хорошее объяснение.   -  person Tensigh    schedule 13.09.2014


Ответы (2)


Прежде всего, комментарии верны: ради вашего здравомыслия вы должны когда-либо работать с юникодом только внутри вашего кода Python, декодировать из Shift-JIS, который приходит, и кодировать обратно в Shift-JIS, если это то, что вам нужно. выход:

text = incoming_bytes.decode("shift_jis")
# ... do stuff ...
outgoing_bytes = text.encode("shift_jis")

См. статью Преобразование текста на границе.

Теперь, когда вы делаете это правильно в отношении unicode и закодированных строк байтов, легко получить либо «любую цифру», либо «любую цифру двойной ширины» с помощью регулярного выражения:

>>> import re
>>> s = u"234"
>>> digit = re.compile(r"\d", re.U)
>>> for d in re.findall(digit, s):
...     print d,
... 
2 3 4
>>> wdigit = re.compile(u"[0-9]+")
>>> for wd in re.findall(wdigit, s):
...     print wd,
... 
2

Если флаг re.U вам незнаком, он задокументирован здесь .

person Zero Piraeus    schedule 12.09.2014
comment
О, shift_jis — это кодировка! По какой-то причине я предполагал, что это JavaScript-фреймворк. Теперь я чувствую себя глупо :) В любом случае, отличный ответ! - person Lukas Graf; 13.09.2014

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

ord("2")

вернется

65298

что находится на расстоянии 65248 пунктов от однобайтовых символов 2. Таким образом, обратное преобразование можно выполнить с помощью:

def convert_two_byte_numbers(character: str):
    if ord(character) in range(65296, 65306):
        return chr(ord(character) - 65248)
    else: 
        return character

Если вам, как и мне, тоже нужно преобразовать двухбайтные буквы, добавьте то же самое для диапазонов (65313, 65339) и (65345, 65371).

person Jérôme Bau    schedule 23.05.2018