Наши партнеры

UnixForum






Книги по Linux (с отзывами читателей)

Библиотека сайта rus-linux.net

На главную -> MyLDP -> Тематический каталог -> Локализация и русификация Linux

Средства Linux для перекодирования файлов

Оригинал: Linux tools to convert file formats
Автор: Federico Kereki
Дата: 22 июля 2008
Перевод: Александр Тарасов aka oioki
Дата перевода: 14 августа 2008

Было бы намного проще, если бы мы жили в мире, в котором существует один лишь Linux, и если бы приложениям не требовались данные из других источников. Однако все еще существует необходимость в получении данных из систем Windows, MS DOS и Macintosh. Импортирование таких документов требует соответствующего перекодирования; иначе было бы невозможно обмениваться данными, или содержимое файлов интерпретировалось бы некорректно. Вообще самый простой способ передавать данные между системами - это с помощью обычных текстовых файлов или в таких форматах как CSV-файлы (значения, разделенные пробелами). Однако преобразование файлов из форматов Windows и Mac OS приводит к различиям в символах новой строки и кодировке символов. В этой статье рассказано, отчего возникают такие проблемы и как их устранить.

Проблема новой строки

Каждая операционная система использует определенный символ (или последовательность символов) для обозначения конца текстовой строки. Нельзя использовать обычные символы для указания новой строки, ведь они могут идти лишь в обычном тексте. Поэтому используется специальный непечатный символ - и у каждой ОС он свой:

Откуда пошли названия символов CR и LF

Раньше (во времена старых принтеров и телетайпов) машины интерпретировали управляющие символы и производили определенные действия. CR (carriage return - возврат каретки) возвращал каретку на первый столбец, а LF (line feed - перевод строки) переводил ее на новую строку на листе бумаги. Управляющий символ FF (form feed) переводил ее на другую страницу. Символы CR и LF обычно представляются в скриптах, регулярных выражениях и исходных кодах в виде последовательностей \r и \n, либо восьмеричными значениями 015 и 012.

  • Linux и Mac OS X унаследовали Unix-стиль и используют LF (управляющий ASCII-символ line feed) в качестве символа конца строки.
  • Старые Macintosh-системы использовали CR (carriage return, другой управляющий ASCII-символ).
  • В Windows используется два символа - CR и затем LF.

Чтобы узнать, какой символ используется в текстовом файле для новой строки, запустите hexdump. С его помощью можно исследовать содержимое файла побайтово. Я подготовил два трехстроковых файла - один на Linux-системе, другой на Windows - и вывел их содержимое побайтово. Файл выводится порциями по 16 байт, отображаются собственно символы и их представления в восьмеричной системе счисления. Обратите внимание, что Linux-файл содержит управляющий символ \n, а Windows - \r и затем \n. На старых Macintosh-системах вы бы увидели одиночный символ \r.

> cat test.linux
This is the first line of a Linux file.
This is the second line.
Here's the last line.

> hexdump -cb test.linux
0000000   T   h   i   s       i   s       t   h   e       f   i   r   s
0000000 124 150 151 163 040 151 163 040 164 150 145 040 146 151 162 163
0000010   t       l   i   n   e       o   f       a       L   i   n   u
0000010 164 040 154 151 156 145 040 157 146 040 141 040 114 151 156 165
0000020   x       f   i   l   e   .  \n   T   h   i   s       i   s
0000020 170 040 146 151 154 145 056 012 124 150 151 163 040 151 163 040
0000030   t   h   e       s   e   c   o   n   d       l   i   n   e   .
0000030 164 150 145 040 163 145 143 157 156 144 040 154 151 156 145 056
0000040  \n   H   e   r   e   '   s       t   h   e       l   a   s   t
0000040 012 110 145 162 145 047 163 040 164 150 145 040 154 141 163 164
0000050       l   i   n   e   .  \n
0000050 040 154 151 156 145 056 012
0000057

> cat test.windows
This is the first line on a Windows file.
This is the second line.
Here's the last line.

> hexdump -cb test.windows
0000000   T   h   i   s       i   s       t   h   e       f   i   r   s
0000000 124 150 151 163 040 151 163 040 164 150 145 040 146 151 162 163
0000010   t       l   i   n   e       o   n       a       W   i   n   d
0000010 164 040 154 151 156 145 040 157 156 040 141 040 127 151 156 144
0000020   o   w   s       f   i   l   e   .  \r  \n   T   h   i   s
0000020 157 167 163 040 146 151 154 145 056 015 012 124 150 151 163 040
0000030   i   s       t   h   e       s   e   c   o   n   d       l   i
0000030 151 163 040 164 150 145 040 163 145 143 157 156 144 040 154 151
0000040   n   e   .  \r  \n   H   e   r   e   '   s       t   h   e
0000040 156 145 056 015 012 110 145 162 145 047 163 040 164 150 145 040
0000050   l   a   s   t       l   i   n   e   .  \r  \n
0000050 154 141 163 164 040 154 151 156 145 056 015 012
000005c

Для преобразования файлов из Windows в Linux можно воспользоваться командой с говорящим названием dos2unix. Самый простой способ преобразовать файл test.windows в формат Linux - запустить

dos2unix test.windows

Однако можно воспользоваться и потоковым вариантом:

dos2unix < test.windows > test.windows.fixed

Все ключи команды можно узнать, посмотрев справку dos2unix -h или man dos2unix.

Для преобразования текстового файла со старой Macintosh-системы необходимо заменить символы CR на LF, это можно сделать с помощью программы tr (translate):

tr "\015" "\012" < старый_Macintosh_файл > новый_Linux_файл
который просто меняет каждый символ CR (восьмеричное 015) на LF (восьмеричное 012). tr также может произвести удаление символа CR для преобразования из Windows-системы, нужно воспользоваться ключом -d. Действие, аналогичное действию ранее упомянутой dos2unix, достигается следующим образом:
tr -d "\015" < test.windows > test.windows.fixed

Проблема кодировки

Помимо обычных 26 символов в английском языке (да и во многих других) используются и специальные типографические символы. Смотрели ли вы фильм Æon Flux и посылали ли curriculum vitæ? В немецком тексте рассыпано множество гласных с умляутами и буквы наподобие ß. В испанском есть разнообразные ň и острые акценты, во французском языке - грависы и циркумфлексы ("pie à la mode"). Если вам нужно набирать такие символы на обычной клавиатуре, обратитесь к этой статье.

Unicode не нужен для обычного английского текста: вполне хватит ASCII-символов, включающих обычные неакцентированные буквы от A до Z, цифры от 0 до 9 и знаки пунктуации. Если вы работаете только с латинским алфавитом, использующимся в странах Западной Европы, то можете сохранять текст в кодировке ISO 8859-1 (неформально ее называют Latin-1), в которой каждый символ занимает один байт, однако в ней невозможно представить символы других языков. Однако в других языках требуется более широкий набор символов и без Unicode не обойтись. Unicode поддерживает более 100 тысяч символов из нескольких десятков языков. Unicode (также известый как стандарт ISO 10646) является расширением ASCII. В то время как ASCII отводит под каждый символ ровно 1 байт, для Unicode-символа требуется больше. Для обеспечения совместимости между ASCII и Unicode обычно используют кодировку UTF-8. В ней для ASCII-символов используется как обычно 1 байт (поэтому ASCII-файл также считается корректным файлом в кодировке UTF-8), а для символов других языков и служебных символов - больше.

Хотя UTF-8 и Latin-1 одинаково кодируют ASCII-символы, однако акцентированные и т.п. символы представляются иначе; поэтому чтобы корректно обработать файл, необходимо знать его формат, иначе все символы, не принадлежащие ASCII-таблице, будут искажены.

Давайте посмотрим, как одна строчка на испанском языке ("¡Que la Fuerza te acompañe!", что означает "Да пребудет с тобой Сила!") представляется в обоих форматах:

> hexdump -cb test.force.utf8
0000000 302 241   Q   u   e       l   a       F   u   e   r   z   a
0000000 302 241 121 165 145 040 154 141 040 106 165 145 162 172 141 040
0000010   t   e       a   c   o   m   p   a 303 261   e   !  \n
0000010 164 145 040 141 143 157 155 160 141 303 261 145 041 012
000001e

> hexdump -cb test.force.latin1
0000000 241   Q   u   e       l   a       F   u   e   r   z   a       t
0000000 241 121 165 145 040 154 141 040 106 165 145 162 172 141 040 164
0000010   e       a   c   o   m   p   a 361   e   !  \n
0000010 145 040 141 143 157 155 160 141 361 145 041 012
000001c

Обратите внимание на символы не из ASCII-таблицы (знак обращенного восклицания в начале и ñ ближе к концу), можно видеть, что в UTF-8 для их кодирования используется два байта, в то время как в Latin-1 всего один. Также видно, что в обоих форматах обычные ASCII-символы кодируются одним байтом.

Требуемая кодировка зависит от используемого приложения. Большинство Linux-программ работают с кодировкой UTF-8, многие другие используют Latin-1, а некоторые обе кодировки сразу. Сначала нужно определить, текст в какой кодировке нужен программе, а затем преобразовывать, если это требуется. К счастью, это можно с легкостью сделать (причем в обоих направлениях), воспользовавшись программой recode.

recode предлагает множество опций (для более подробной справки наберите recode --help или info recode), ей можно воспользоваться для преобразования текста в разнообразные кодировки (для получения полного списка поддерживаемых кодировок введите recode -l). Однако для простых преобразований достаточно команд:

recode UTF-8..ISO-8859-1 test.force.utf8
recode ISO-8859-1..UTF-8 test.force.latin1
(на выходе получится текст в кодировке Latin-1 и UTF-8 соответственно)

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

Заключение

Преобразование текстовых файлов из других операционных систем - не прямой процесс, однако в Linux для этого есть все средства. Неважно какой формат файла, всегда можно автоматизировать требуемое преобразование и работать с разными несовместимыми форматами.