/ / Por que o Iconv funciona de maneira diferente no irb e no interpretador Ruby? - ruby, irb, iconv

Por que o Iconv funciona diferente no irb e no interpretador Ruby? - rubi, irb, iconv

Eu tenho que converter caracteres latinos como éáéíóúÀÉÍÓÚ etc., em uma seqüência de caracteres semelhantes sem acentos especiais ou símbolos com fio:

é -> e
è -> e
Ä -> A

Eu tenho um arquivo chamado "test.rb":

require "iconv"

puts Iconv.iconv("ASCII//translit", "utf-8", "è").join

Quando colo essas linhas no irb, ele funciona, retornando "e" conforme o esperado.

Corrida:

$ ruby test.rb

Eu recebo "?"como saída.

Estou usando irb 0.9.5 (05/04/13) e Ruby 1.8.7 (2011-06-30 patchlevel 352) [i386-linux].

Respostas:

3 para resposta № 1

Ruby 1.8.7 não era conhecedor de caracteres multibyte como 1.9+. Em geral, trata uma string como uma série de bytes, em vez de caracteres. Se você precisar lidar melhor com esses personagens, considere atualizar para 1.9+.

James Gray tem um série de artigos sobre como lidar com caracteres multibyte no Ruby 1.8. Eu recomendo fortemente que você reserve um tempo para lê-los. É um assunto complexo, então você vai querer ler a série inteira que ele escreveu algumas vezes.

Além disso, o suporte à codificação 1.8 precisa do $KCODE conjunto de sinalizadores:

$KCODE = "U"

portanto, você precisará adicioná-lo ao código em execução no 1.8.

Aqui está um pequeno código de amostra:

#encoding: utf-8

require "rubygems"
require "iconv"

chars = "éáéíóúÀÉÍÓÚ"

puts Iconv.iconv("ASCII//translit", "utf-8", chars)

puts chars.split("")
puts chars.split("").join

Usando ruby ​​1.8.7 (2011-06-30 patchlevel 352) [x86_64-darwin10.7.0] e executando-o no IRB, obtenho:

1.8.7 :001 > #encoding: utf-8
1.8.7 :002 >
1.8.7 :003 >   require "iconv"
true
1.8.7 :004 >
1.8.7 :005 >   chars = "303251303241303251303255303263303272303200303211303215303223303232"
"303251303241303251303255303263303272303200303211303215303223303232"
1.8.7 :006 >
1.8.7 :007 >   puts Iconv.iconv("ASCII//translit", "utf-8", chars)
"e"a"e"i"o"u`A"E"I"O"U
nil
1.8.7 :008 >
1.8.7 :009 >   puts chars.split("")
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
nil
1.8.7 :010 > puts chars.split("").join
éáéíóúÀÉÍÓÚ

Na linha 9 da saída, disse a Ruby para dividir olinha em seu conceito de caracteres, que em 1.8.7, era bytes. O resultado "?" significa que não sabia o que fazer com a saída. Uma linha 10 que pedi para dividir, o que resultou em uma matriz de bytes, que join em seguida, remontado na string normal, permitindo que os caracteres multibyte sejam traduzidos normalmente.

Executar o mesmo código usando Ruby 1.9.2 mostra um comportamento melhor, mais esperado e desejável:

1.9.2p290 :001 > #encoding: utf-8
1.9.2p290 :002 >
1.9.2p290 :003 >   require "iconv"
true
1.9.2p290 :004 >
1.9.2p290 :005 >   chars = "éáéíóúÀÉÍÓÚ"
"éáéíóúÀÉÍÓÚ"
1.9.2p290 :006 >
1.9.2p290 :007 >   puts Iconv.iconv("ASCII//translit", "utf-8", chars)
"e"a"e"i"o"u`A"E"I"O"U
nil
1.9.2p290 :008 >
1.9.2p290 :009 >   puts chars.split("")
é
á
é
í
ó
ú
À
É
Í
Ó
Ú
nil
1.9.2p290 :010 > puts chars.split("").join
éáéíóúÀÉÍÓÚ

Ruby manteve o multibyte-ness dos personagens, através do split("").

Observe que, em ambos os casos, Iconv.iconv fez a coisa certa, criou personagens queeram visualmente semelhantes aos caracteres de entrada. Embora o apóstrofo inicial pareça fora do lugar, está lá como um lembrete de que os caracteres foram acentuados originalmente.

Para obter mais informações, consulte os links à direita para perguntas relacionadas ou tente esta pesquisa SO para [ruby] [iconv]