«Хвост -f | iconv -fsjis »ничего не выводит

14

Я хочу tail -fфайл, но его содержимое находится в sjisкодировке, поэтому мне нужно преобразовать его в собственную (utf-8) кодировку моего терминала.

Когда я делаю

хвост -fx | iconv -fsjis

не будет никакого выхода. В качестве

хвост х | iconv -fsjis

делает работу, сначала я подумал , что это был вопрос буферизации, но пытаюсь unbufferи , stdbufкак описано на повороте от буферизации в трубе не помогут.

На самом деле, даже после того, как в x было добавлено более 10 тыс. Данных, выходных данных не будет, поэтому я полагаю, что это не проблема буферизации (буфер равен 4 тыс., Если я не ошибаюсь), но iconv начнет выводить только тогда, когда он получает EOF.

Итак, как я могу следить за моим файлом, закодированным в sjis?

Евгений Бересовский
источник

Ответы:

11

(возьмите это с щепоткой соли) Насколько я помню, проблема заключается в том, как libiconvработает. Многобайтовым кодировкам нужен конечный автомат для их декодирования, и он libiconvпредпочитает получать целые символы, поэтому вы не можете просто дать ему половину символа в одном вызове функции, а другую половину - в следующем.

Я могу придумать еще два решения: одно - хороший внеполосный метод, другое - внутриполосный хак.

Изменить кодировку эмулятора терминала (внеполосно) : один из них - изменить кодировку символов в эмуляторе терминала, поэтому его родной кодировкой является Shift JIS. Я только что проверил konsole, и это поддерживает. В меню View → Кодировка символов → Japenese → sjis. Затем вы можете просто tail -fфайл и konsoleпозаботиться о декодировании многобайтовых символов и сопоставлении их до глифов шрифта.

Транскодирование терминала на лету (внутриполосное; лучшее) : любезно предоставлено Жилем, который напомнил мне luitпосле очень долгого времени. Используйте luit, который должен был поставляться с вашим дистрибутивом XOrg (в Debian это пакет x11-utils). Используйте это так:

$ luit -encoding SJIS -- tail -f x

Это заставит терминал перекодировать SJIS в кодировку вашего терминала и запустить его tail -f x. Недостатком luitявляется то, что он не поддерживает множество поддерживаемых кодировок libiconv. Плюс это доступно практически везде.

Транскодирование терминального кодирования на лету (in-band; hack) : ttyconvэто хак, который я написал много лет назад (первоначально в C, позже переделанный в Python), который используется libiconvдля перекодирования терминального ввода-вывода. Он порождает новый псевдотерминал и (а) транскодирует символы, которые вы вводите из вашей локальной кодировки, в удаленную кодировку, и (б) транскодирует символы, которые вы получаете от удаленной кодировки, в вашу локальную кодировку. Я использовал его для общения с серверами, которые использовали кодировки, не поддерживаемые стандартными терминалами Linux. Обратите внимание, что все удаленные кодировки, которые я тестировал, были однобайтовыми, поэтому я не могу гарантировать, что это будет работать для Shift JIS. В наши дни я не часто обращаюсь к нему с призывом использовать большинство систем, переключающихся на Unicode.

Вот как вы бы это использовали:

$ ttyconv -rsjis -- tail -f x

Недостатком ttyconvявляется то, что я написал это, никто не использует его, кроме меня, вероятно, он полон ошибок. Я преуспеваю в этом. Плюс в том, что он использует libiconv, поэтому, если ваша кодировка необычна, это ваш лучший выбор. По последним подсчетам, ttyconv --listподдерживает 100 кодировок.

Алексиос
источник
Здорово, спасибо. внеполосный не работал для меня (gnome-терминал, хотя он позволяет вам изменять кодировку), но ttyconv работает как чудо.
Евгений Бересовский
2
В наши дни есть luitчасть стандартного пакета утилит X11, который похож на ваш ttyconv.
Жиль "ТАК - перестань быть злым"
@Gilles luitпохож, за исключением того, что он работает намного лучше, чем у меня. ;) Благодарность! Вот почему я перестал использовать в первую очередь. За 12 лет, прошедших с тех пор, как мне удалось забыть даже название команды, я искал его с тех пор.
Алексиос
@ Жиль luitработает для меня тоже. Почему бы вам не сделать это «официальным» ответом? Он был частью моей установки (Debian), и, следовательно, его проще всего использовать для меня.
Евгений Бересовский
1
Я обновил ответ, чтобы включить luitкак лучший выбор для SJIS. К сожалению, кажется, что он не поддерживает все кодировки libiconv. Похоже, я все еще должен использовать свое собственное решение для своих сюрреалистических целей. :)
Алексиос