“Cauda -f | iconv -fsjis ”não produz nada

14

Quero tail -fum arquivo, mas seu conteúdo está em sjiscodificação, portanto, preciso convertê-lo para a codificação nativa (utf-8) do meu terminal.

Quando eu faço

cauda -fx | iconv -fsjis

não haverá saída. Como

cauda x | iconv -fsjis

funciona, no começo eu pensei que era um problema de buffer, mas tentar unbuffere stdbufconforme descrito em Desligar o buffer no pipe não ajudou.

De fato, mesmo depois que mais de 10k de dados foram adicionados ao x, não haveria saída, então acho que não é um problema de buffer (o buffer é de 4k, se não me engano), mas o iconv só começará a produzir quando recebe um EOF.

Então, como posso seguir o meu arquivo codificado sjis?

Eugene Beresovsky
fonte

Respostas:

11

(leve isso com uma pitada de sal) Até onde me lembro, o problema está no modo como libiconvfunciona. As codificações de vários bytes precisam de uma máquina de estado para decodificá-las e libiconvpreferem receber caracteres inteiros; portanto, você não pode atribuir apenas meio caractere em uma chamada de função e a outra metade na seguinte.

Posso pensar em outras duas soluções, uma é um bom método fora da banda, a outra é um hack na banda.

Alterar a codificação do Terminal Emulator (fora da banda) : uma é alterar a codificação de caracteres no emulador de terminal, para que sua codificação nativa seja Shift JIS. Acabei de verificar konsole, e é suporta isso. No menu, Exibir → Codificação de caracteres → Japonês → sjis. Você pode então apenas tail -fo arquivo e konsolecuidará da decodificação dos caracteres multibyte e da correspondência deles com os glifos da fonte.

Codificação de terminal de transcodificação em tempo real (dentro da banda; melhor) : cortesia de Gilles, que me lembrou luitdepois de muito tempo. Use luit, que deveria ter vindo com sua distribuição XOrg (no Debian, é pacote x11-utils). Use-o assim:

$ luit -encoding SJIS -- tail -f x

Isso fará com que o terminal transcodifique o SJIS de / para a codificação do terminal e execute tail -f x. A desvantagem luité que ele não suporta a riqueza de codificações suportadas por libiconv. A vantagem é que está disponível em quase todos os lugares.

Codificação de terminal de transcodificação em tempo real (dentro da banda; hack) : ttyconvé um hack que escrevi há muitos anos (inicialmente em C, posteriormente refeito em Python) que é usado libiconvpara transcodificar a E / S do terminal. Ele gera um novo pseudoterminal e (a) transcodifica os caracteres digitados da codificação local para a codificação remota e (b) transcodifica os caracteres que você recebe da codificação remota para a codificação local. Usei-o para conversar com servidores que usavam codificações não suportadas pelos terminais padrão do Linux. Observe que todas as codificações remotas com as quais eu testei eram de byte único, portanto não posso garantir que funcione para o Shift JIS. Não costumo encontrar chamadas para usá-lo atualmente, com a maioria dos sistemas alternando para Unicode.

É assim que você o usaria:

$ ttyconv -rsjis -- tail -f x

A desvantagem ttyconvé que eu escrevi, ninguém usa, exceto eu, provavelmente está cheio de bugs. Eu me supero nisso. O lado positivo é que ele usa libiconv, portanto, se sua codificação é incomum, é sua melhor aposta. Na última contagem, ttyconv --listsuporta 100 codificações.

Alexios
fonte
Incrível, obrigado. o out-of-band não funcionou para mim (terminal gnome, embora permita alterar a codificação), mas o ttyconv funciona como um encanto.
Eugene Beresovsky
2
Atualmente, há luitparte do pacote de utilitários X11 padrão, que é semelhante ao seu ttyconv.
Gilles 'SO- stop be evil'
@Gilles luité semelhante, exceto que funciona muito melhor que o meu. ;) Obrigado! É por isso que parei de usar em primeiro lugar. Nos 12 anos desde que consegui esquecer até o nome do comando, tenho procurado desde então.
Alexs #
@Gilles também luittrabalha para mim. Por que você não faz uma resposta 'oficial'? Fazia parte da minha instalação (debian) e, portanto, é o mais fácil de usar para mim.
Eugene Beresovsky 9/04/12
1
Atualizei a resposta para incluir luitcomo a melhor opção para o SJIS. Infelizmente, parece que não suporta todas as codificações libiconv. Parece que ainda preciso usar minha própria solução para meus propósitos surreais. :)
Alexios