Мне нужен tail -f
файл, но его содержимое закодировано sjis
, поэтому мне нужно преобразовать его в собственную кодировку (utf-8) моего терминала.
Когда я делаю
хвост -fx | iconv -fsjis
не будет никакого выхода. Как
хвост x | iconv -fsjis
работает, сначала я думал, что это проблема буферизации, но попробовав unbuffer
и stdbuf
как описано наОтключить буферизацию в каналене помогло.
На самом деле, даже после добавления более 10 КБ данных в x вывода не будет, поэтому я предполагаю, что это не проблема буферизации (буфер составляет 4 КБ, если я не ошибаюсь), но iconv начнет выводить данные только после получения EOF.
Итак, как мне отследить мой файл, закодированный в формате SJIS?
решение1
(отнеситесь к этому с долей скепсиса) Насколько я помню, проблема в том, как libiconv
работает. Многобайтовые кодировки требуют конечного автомата для их декодирования и libiconv
предпочитают получать целые символы, так что вы не можете просто передать ему половину символа в одном вызове функции, а другую половину — в следующем.
Я могу придумать еще два решения: одно — хороший внеполосный метод, другое — внутриполосный хак.
Изменить кодировку эмулятора терминала (внеполосно): один из них — изменить кодировку символов в вашем эмуляторе терминала, чтобы его родная кодировка была Shift JIS. Я только что проверил konsole
, и он поддерживает это. Из меню, Вид→Кодировка символов→Японский→sjis. Затем вы можете просто tail -f
файл, и konsole
он позаботится о декодировании многобайтовых символов и сопоставлении их с глифами шрифта.
Перекодирование терминального кодирования на лету (внутриполосное; лучшее): любезно предоставлено Жилем, который напомнил мне о luit
после очень долгого перерыва. Используйте luit
, который должен был быть в вашем дистрибутиве XOrg (в Debian это пакет x11-utils
). Используйте его так:
$ luit -encoding SJIS -- tail -f x
Это заставит терминал перекодировать SJIS в/из кодировки вашего терминала и запустить tail -f x
. Недостатком luit
является то, что он не поддерживает множество кодировок, поддерживаемых libiconv
. Преимуществом является то, что он доступен практически везде.
Перекодирование терминального кодирования на лету (внутриполосное; хак):ttyconv
это хак, который я написал много лет назад(первоначально на C, позже переделано на Python), который используется libiconv
для перекодирования терминального ввода-вывода. Он порождает новый псевдотерминал и (a) перекодирует символы, которые вы вводите, из вашей локальной кодировки в удаленную кодировку, и (b) перекодирует символы, которые вы получаете из удаленной кодировки в вашу локальную кодировку. Я использовал его для связи с серверами, которые использовали кодировки, не поддерживаемые стандартными терминалами Linux. Обратите внимание, что все удаленные кодировки, с которыми я его тестировал, были однобайтовыми кодировками, поэтому я не могу гарантировать, что он будет работать для Shift JIS. Я не часто нахожу необходимость использовать его в наши дни, поскольку большинство систем переходят на Unicode.
Вот как это можно использовать:
$ ttyconv -rsjis -- tail -f x
Недостаток в ttyconv
том, что я написал его, никто им не пользуется, кроме меня, он, вероятно, полон ошибок. Я преуспел в этом. Плюс в том, что он использует libiconv
, так что если ваша кодировка необычная, это ваш лучший выбор. По последним подсчетам, ttyconv --list
поддерживает 100 кодировок.
решение2
Похожая программа ttyconv
есть также tconv
, написанная на языке C Ричем Фелкером.