LINUX.ORG.RU

питон: отдельные символы в строке(часть 2) или следует выбрать другой язык?


0

0

Задача: есть текствой файл в почти весь в DOS кодировке
с вкраплениями ввида <<текст>>, где текст имеет специальную кодировку(имеется
таблица соотвествия юникоду).
Надо перевести все в одну кодировку(какой-нибудь unicode) , а потом обработать.

хочется чтобы это выглядело

convert_table = { 'a': unichr(....) }

f = open(args[0], 'r')

for line in f.readlines():
replace(line, '<<.*>>'->convert_table else convert_from('cp866'))
#handle line

f.close()

но как я понимаю
1)f.readlines() использовать нельзя, т.к. строки неявно преобразуются
из локальной кодировки во внутренее представление строк питона,
т.е. если локально ru_RU.UTF-8, то будет по умолчанию считаться что строки
в utf-8
2)чего-то подобного replace не существует, да и невозможно сказать,
типа все что в "<<" ">>" переконвертировать так-то, а все остальное так-то.
3)для того чтобы работать со строкой как с массивом байт, надо использовать
черную магию типа pack, unpack.


т.е. имеется желание написать только алгоритм, а не скатываться до описания
алгоритма поиска '<<', проверки следует ли за ним '>>' и т.д.

Возможно ли это на питоне, если нет может следует обратить внимание
на perl, ruby, ...?

anonymous

>хочется чтобы это выглядело

Кошернее было бы написать encoder/decoder, как его хочет видеть питон, а потом писать f.readline.decode('МояКодировка').

>1)f.readlines() использовать нельзя, т.к. строки неявно преобразуются

Насколько мне известно неявно строки никуда не преобразуются, если не звать unicode.

>2)чего-то подобного replace не существует, да и невозможно сказать

Если сильно хочется, можно обойтись regexp-ами, типа

esc=re.compile('<<(.*)>>')
dosenc=esc.split(line)
specenc=esc.findall(line)
rez=''.join([x.decode('cp866')+y.decodeПоСвоему() for (x,y) in zip(dosenc,specenc)])

Но это неправильно.

>3)для того чтобы работать со строкой как с массивом байт, надо использовать черную магию типа pack, unpack.

Неправильно.

DonkeyHot ★★★★★
()
Ответ на: комментарий от anonymous

>а что тогда правильно

п.1 - написать правильный декодер. Приведеный пример с регекспами с большой вероятностью будет плохо работать во всяких крайних случаях - типа лишних "<<>>", неуместный перевод строки, пр.

DonkeyHot ★★★★★
()

>f.readlines() использовать нельзя, т.к. строки неявно преобразуются из локальной кодировки во внутренее представление строк питона

Неправда.

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

Неправда. Строка - это и есть массив байт. И UTF-8 тут не причем.

ps. (я бы еще со split("<<", 1) поигрался, если бы точно знал, что в <</>> нет нарушения порядка.)

smartly ★★★
()

Re:

>f = open(args[0], 'r') 
agrs[0] ето имя программы, нужен args[1]:-)

Вообще такие вещи делаются через фильры, читаешь входной поток, перекодируешь, пишешь в выходной - куда гибче и проще.

Про строки и readlines - кто Вам это сказал? readlines это список векторов байт, ничего никуда не перекодируется, даже \n в конце висят...
Всякие split, replace и тд есть в полном объеме, наберите dir('')
Очень мощный оператор форматирования %, позволяет выводить значения из словаря по ключу и тд, очень развесисистая штука.

Как конкретно ловить << >>... смотрите сами, я бы обошелся и без регэспов наверное...

AIv ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.