Kodomo

Пользователь

Учебная страница курса биоинформатики,
год поступления 2018

Комментарии к практикуму 8

Кодировка файлов скриптов

Узнать кодировку файла

Проверить кодировку файла можно с помощью команды file. Главная функция этой команды – угадать тип файла по его содержимому, но она умеет определять и основные типы кодировок. Чтобы показать, в том числе, кодировку, есть опция -i, чтобы показать только кодировку тоже есть опция (--mime-encoding), но её сложнее набирать.

В случае кодировки UTF-8 будет написано "charset=utf-8", или "charset=us-ascii", если в вашем файле только символы из первой половины кодовой таблицы ASCII (т.е., только цифры, английские буквы, простые знаки препинания, пробельные символы и еще кое-что, более менее все, что можно найти на клавиатуре в английской раскладке), которые в UTF-8 кодируются так же, как в ASCII.

В случае, CP1251 (она же Windows-1251 и ANSI по версии Far, стандартная 8-битная кодировка для русского языка в Windows), CP866 (устаревшая 8-битная кодировка для русского языка в Windows), KOI8-R (устаревшая 8-битная кодировка для русского языка в Unix-подобных операционных системах) будет напечатано "charset=iso-8859-1" (file не умеет различать почти никакие 8-битные ASCII-совместимые кодировки).

Если вам вдруг все-таки надо точно определить кодировку файла, можете использовать команду chardet.

Как поменять кодировку файла

Для изменения кодировки текстовых файлов существует команда iconv. Стандартный способ запуска следующий:

   1 iconv -f FROM -t TO OLD_FILE | less # чтобы убедиться, что смена кодировки происходит удачно
   2 iconv -f FROM -t TO OLD_FILE > NEW_FILE # чтобы сохранить перекодированный текст в файл NEW_FILE
   3 

FROM и TO – названия кодировок, которые понимает iconv, а OLD_FILE и NEW_FILE – имена файлов. Полный список всех поддерживаемых названий кодировок можно узнать с помощью опции -l:

   1 iconv -l | less # список длинный!
   2 

В вашем случае команда почти наверняка будет следующая:

   1 iconv -f cp1251 -t utf8 OLD_FILE > NEW_FILE

Проблемы с UTF-8 (BOM)

С кодировкой UTF-8 есть некоторая подстава, про которую я каждый раз забываю рассказать. Эта кодировка допускает в самом начале файла присутствие так называемого BOM (byte order mark) – специального символа Unicode, который в случае UTF-8 кодируется тремя байтами 0xEF 0xBB 0xBF. BOM не является обязательным или даже рекомендуемым для UTF-8, но некоторые программы его добавляют при сохранении файла в кодировке UTF-8. Например, Far поступает именно так, и не только Far.

Все программы, которые умеют понимать UTF-8, обычно правильно обрабатывают этот символ и просто игнорируют его при отображении текста. Но с шебангом (#!) начинаются проблемы. Как я вам говорил, символы #! должны быть в самом начале файла, иначе они не работают, в том числе, если перед ними стоит BOM, который ещё и не отображается в текстовом редакторе.

Выход простой – удалить BOM. Но проще сказать, чем сделать. Для начала надо убедиться, что он действительно есть. Самый простой способ – посмотреть файл в less. Если в начале файла есть BOM, то он будет отображаться в виде <U+FEFF> в начале первой строки.

Теперь вам надо удалить первый символ или 3 первых байта (в этом случае). Это можно сделать кучей разных способов. Например, с помощью sed:

   1 sed -Ei '1s/^.//' FILE # -i для изменения файла "на месте", используйте с осторожностью!
   2 # 1 - адрес первой строки
   3 # s/^.// - удаление любого первого символа в строке
   4 

На самом деле, в случае скриптов, начинающихся с #!, можно использовать следующую команду, независимо от того, был в начале BOM, или нет:

   1 sed -Ei '1s/^[^#]*#/#/' FILE # -i для изменения файла "на месте", используйте с осторожностью!
   2 # 1 - адрес первой строки
   3 # s/^[^#]*#/#/ - удаление любого количества любых символов до первого символа #
   4 

Кодировка переносов строк

Существует всего два распространенных способа кодировать переносы строк в текстовых файлах: стиль Windows и стиль Unix. Как не сложно догадаться, почти все программы в Linux ожидают переносы строк в стиле Unix.

В Windows переносы строк кодируются двумя символами CR (возврат каретки) и LF (перевод строки). В Unix – одним символом LF. Самый простой способ привести файл к Unix формату – просто удалить из него всего символы CR вообще, если они есть. Для этого можно использовать команду tr -d.

   1 cat OLD_FILE | tr -d "\r" > NEW_FILE # \r распространенное обозначение CR, \n -- LF, \t -- TAB
   2 # OLD_FILE и NEW_FILE должны быть разными файлами! Иначе потеряете все содержимое.
   3 # или
   4 tr -d "\r" < OLD_FILE > NEW_FILE

Проверить наличие CR в файле можно с помощью:

   1 less -U FILE # отображает CR как ^M и TAB на ^I
   2 cat -A FILE | less # cat -A меняет CR на ^M, LF на $ и TAB на ^I
   3