为什么Iconv在irb和Ruby解释器中的工作方式不同?

时间:2011-12-09 12:55:20

标签: ruby irb iconv

我必须将像éáéíóúÀÉÍÓÚ等拉丁字符转换为字符串,而不是特殊的重音或有线符号的字符串:

é -> 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]。

1 个答案:

答案 0 :(得分:3)

Ruby 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

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

Ruby通过split('')保持字符的多字节。

请注意,在这两种情况下,Iconv.iconv做了正确的事情,它创建了与输入字符在视觉上相似的字符。虽然领先的撇号看起来不合适,但它提醒人们最初对角色进行了重音。

有关详细信息,请参阅相关问题右侧的链接或尝试使用[ruby] [iconv] {{1}}