2011-12-09 98 views
4

我不得不拉丁字符转换像éáéíóúÀÉÍÓÚ等,转换成字符串类似那些无特殊口音或有线符号:为什么Iconv在irb和Ruby解释器中工作不同?

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

我有一个文件名为“test.rb”:

require 'iconv' 

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

当我将这些行粘贴到irb中时,它会按预期返回“e”。

运行:

$ ruby test.rb 

我得到 “?” 作为输出。

我使用irb 0.9.5(05/04/13)和Ruby 1.8.7(2011-06-30 patchlevel 352)[i386-linux]。

+0

是,被编码成UTF-8。它也是默认的系统编码。 我觉得它也行不通,因为如果我有良好的记忆力,1.9版本中就会引入“#encoding”魔术评论。 虽然我刚刚尝试过,但不起作用。 – zambotn

回答

3

红宝石1.8.7不是像1.9+是多字节字符精明。通常,它将字符串视为一系列字节,而不是字符。如果您需要更好地处理这些角色,请考虑升级到1.9+。

James Gray有一个关于在Ruby 1.8中处理多字节字符的series of articles。我强烈建议花时间阅读它们。这是一个复杂的主题,所以你需要阅读他编写的整个系列。

此外,1.8编码的支持需要$KCODE标志设置:

$KCODE = "U" 

所以你需要将它添加到代码运行在1.8。

这里是一个比特的示例代码:

#encoding: UTF-8 

require 'rubygems' 
require 'iconv' 

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

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

puts chars.split('') 
puts chars.split('').join 

使用红宝石1.8.7(2011-06-30 PATCHLEVEL 352)[x86_64的-darwin10.7.0]和在IRB运行它,我得到:

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 = "\303\251\303\241\303\251\303\255\303\263\303\272\303\200\303\211\303\215\303\223\303\232" 
"\303\251\303\241\303\251\303\255\303\263\303\272\303\200\303\211\303\215\303\223\303\232" 
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 
éáéíóúÀÉÍÓÚ 

在输出的第9行,我告诉Ruby将行分割成它在1.8.7中的字符概念,它是字节。所结果的 '?'意味着它不知道如何处理输出。我告诉它分割的第10行产生了一个字节数组,然后join重新组装成普通字符串,从而允许多字节字符正常转换。

运行使用Ruby 1.9.2相同的代码示出了更好,更期望的和合乎需要的,行为:

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 
éáéíóúÀÉÍÓÚ 

红宝石保持的字符的多字节岬,通过split('')

请注意,在这两种情况下,Iconv.iconv都做得对,它创建的视觉效果与输入字符相似。虽然主要的撇号看起来不合适,但它在那里提醒人物原本是重音符号。

欲了解更多信息,请参见右侧的链接到相关的问题或尝试this SO search[ruby] [iconv]

+0

好,非常感谢你,我明白了一点!现在我有两个问题:第一,我不能升级版本,因为软件必须工作在1.8.7上,第二个是标题:如果我用'ruby'(而不是IRB)运行你的脚本,输出不同,似乎Iconv在这种情况下不起作用。 – zambotn

+0

而且我的第七行的输出是不同的:我有'eaeiouAEIOU'而不是''e'a'e'i'o'u''E'I'O'U'。 – zambotn

+0

Ruby 1.9+自动执行'require'rubygems'',所以您需要将它添加到1.8.7的脚本中。我会将其添加到我的示例中以减少混淆。 –

相关问题