论坛首页 编程语言技术论坛

UTF8编码和正则表达式

浏览 25354 次
该帖已经被评为良好帖
作者 正文
   发表时间:2009-04-17   最后修改:2009-04-17
ruby的编码问题是每一个ruby初学者的最大困扰。下面把我的总结和大家分享一下,希望对大家有帮助。
注:系统windows xp 平台:ruby 1.8.6 (without rails)
1。编辑器
windows下大多数编辑器(比如irb,ruby自带的SciTE)不支持UTF-8编码,所以解决编码问题最先是换个支持UTF-8编码的编辑器,比如Netbeans,这样才能保证你的输入字符编码是UTF-8.
有了UTF-8编码的编辑器还不够,还要保证输出端不出现乱码,那就一定要用iconv这个库转换。因为ruby程序输出都是在windows 的cmd控制台的,而控制台的编码是GBK。
require'iconv'
class String
 def to_gbk
  Iconv.iconv("GBK//IGNORE","UTF-8//IGNORE",self).to_s
 end
 def to_utf8
  Iconv.iconv("UTF-8//IGNORE","GBK//IGNORE",self).to_s
 end
end
utf8_string="\344\273\254"
puts utf8_string #在irb中输出“浠”=>乱码
puts utf8_string.to_gbk #在irb中输出“们”=>正确输出
#在irb输入一汉字
gbk_string="\303\307"
puts gbk_string #输出"们"
p gbk_string.to_utf8 #输出"\344\273\254"

判断一个段文本是否是UTF-8编码:
class String
 def utf8?  
        unpack('U*') rescue return false  
        true  
 end
end
utf8_string.utf8? #true
gbk_string.utf8? #false


上面介绍了如何输入,显示,判断和转换utf8字符。但是只有这些还不够,下面绍如何处理。
ruby默认处理字符是按照ascii编码方式(这个和你输入的编码方式无关)
比如:
puts utf8_string.size #输出3
puts gbk_string.size #输出2

从这个例子我们可以看到,size方法的返回值实际上是这个字符串在某个固定的字符集下被编码为几个字节,从而返回它
jcode库还提供了一些有用的方法,比如jlength和each_char.
用jcode之前必须设置$KCODE="UTF-8"
$KCODE="u"
require'jcode'
puts utf8_string.size #还是3
puts utf8_string.jsize #1,正是我们想要的结果
puts gbk_string.jsize #也是1

这里还有一个方法,叫做mbchar?的,他检测一个字符串是否是多字节的.
puts utf8_string.mbchar? #0
puts gbk_string.mbchar? #nil 这个有点问题了.....
puts "aaaaa".mbchar? #nil

jcode库还重新定义了chop, delete, squeeze, succ, tr, 和tr_s.这些方法.这些方法都是为多字节的字符串所定义的
我们还可以使用each_char来打印出所有的多字节字符:
str=utf8_string << "hello"
str.each_char.map {|e| e.to_gbk} #=> ["们", "h", "e", "l", "l", "o"]
str.each_char.map {|e| [e.size,e.jsize]} #=> [[3, 1], [1, 1], [1, 1], [1, 1], [1, 1], [1, 1]]

unpack方法,有选项来帮助我们操作unicode字符串,如果他的参数为U*的话,则将会解码当前的字符串,使用utf-8编码。也就是说他会返回一个整数数组,而对应的还有一个pack方法,他则是编码的:
string=(utf8_string << "hooopo")*10
puts string.unpack("U*") #=> [20204, 104, 111, 111, 111, 112, 111, 20204, 104, 111, 111, 111, 112, 111, #20
#204, 104, 111, 111, 111, 112, 111, 20204, 104, 111, 111, 111, 112, 111, 20204, 1
#04, 111, 111, 111, 112, 111, 20204, 104, 111, 111, 111, 112, 111, 20204, 104, 11
#1, 111, 111, 112, 111, 20204, 104, 111, 111, 111, 112, 111, 20204, 104, 111, 111
#, 111, 112, 111, 20204, 104, 111, 111, 111, 112, 111]

用unpack做提取中文字符等操作是相当强大的:
string.unpack("U*").select{|e| (0x4E00..0x9FA5).include?e}.pack("U*").to_gbk
 #=> "们们们们们们们们们们"

当然提取中文可以用scan
string.scan(/./u).select{|e| e.size==3}.join.to_gbk
#=> "们们们们们们们们们们"

有个bug就是size==3的不一定是中文,也有可能是日文。。。但是这个对处理中文网页是没什么问题的。
提取字符串最强大的还是正则表达式,不过对中文这个问题,貌似ruby1.8.6的正则表达式不是很好处理
s=[0x4E00].pack("U")
e=[0x9FA5].pack("U")
reg=Regexp.new("[#{s}-#{e}]",false,"U")
puts string.scan(reg).join.to_gbk
#=> "们们们们们们们们们们"


这里说明一下,虽然ruby默认处理字符串的方式是按照ascii,但是如果设置$KCODE="u"会按照UTF-8方式处理,但是在正则表达式中只要设置正则字面量u(/reg/u)就会安装utf8方式处理,多以,如果知道要匹配字符范围的话,ruby 1.8.6的正则表达式也能很好的处理utf8
其他相关:
1.这里是pack和unpack的中文介绍http://www.souzz.net/html/345/23498.html
2.ruby每周一测-中英文混合字符串截取http://www.iteye.com/topic/201531
3. icu4r: IBM ICU库的Ruby扩展,添加了诸如UString, URegexp等类来处理Unicode。(文档链接)http://icu4r.rubyforge.org/
4.utf8proc: 一个很小型的库,便利字符串中的的字符然后一个个转过去,给String类和Interger类添加了了一些方法,比如String#utf8map和Integer#utf8 http://www.flexiguided.de/publications.utf8proc.en.html

   发表时间:2009-04-17  

SciTE 支持 UTF-8

# Internationalisation
# Unicode
code.page=65001
#character.set=134
# Required for Unicode to work on GTK+:
#LC_CTYPE=en_US.UTF-8
output.code.page=

 

5 请登录后投票
   发表时间:2009-04-17  
devworks 写道

SciTE 支持 UTF-8

# Internationalisation
# Unicode
code.page=65001
#character.set=134
# Required for Unicode to work on GTK+:
#LC_CTYPE=en_US.UTF-8
output.code.page=

 


原来在Options=>SciTEGlobal.properties里面设置啊!!谢谢~~

0 请登录后投票
   发表时间:2009-04-18  
更正一点:
SciTE是支持UTF-8的,在SciTE做如下设置

# Internationalisation
# Japanese input code page 932 and ShiftJIS character set 128
#code.page=932
#character.set=128
# Unicode
code.page=65001 #你输入的代码的编码的编码方式设置为UTF-8
#code.page=0
#character.set=204
# Required for Unicode to work on GTK+:
#LC_CTYPE=en_US.UTF-8
output.code.page=65001 #ScitE控制台输出编码设置为UTF-8,这样按F5后输出编码即为UTF-8

0 请登录后投票
   发表时间:2009-04-18   最后修改:2009-04-18
以前一直用cmd做输出端,被输出的乱码困扰很久,原来SciTE可以设置输出端编码方式,我火星了!!
0 请登录后投票
   发表时间:2009-04-18  
如果你不是用的cmd或irb做输出端,可以把上面示例代码中的to_gbk去掉。
0 请登录后投票
   发表时间:2009-04-20  
正则表达式是支持utf-8,但支持GBK不好

ruby有没有多字节处理类?可任意转换的?

如php中有mb_string,可以多数编码长度,取子串,支持中英文
0 请登录后投票
   发表时间:2009-04-20  
如果在LINUX下面写代码,与出来一般是UTF-8的.有时候也需要转化成 GB18030 才能兼容 WINDOWS 系统.
0 请登录后投票
   发表时间:2009-04-20  
tanggq 写道
正则表达式是支持utf-8,但支持GBK不好

ruby有没有多字节处理类?可任意转换的?

如php中有mb_string,可以多数编码长度,取子串,支持中英文

是的,貌似ruby 1.9的正则好很多。
标准库貌似只有jcode库吧~~
0 请登录后投票
   发表时间:2009-04-20  
sevk 写道
如果在LINUX下面写代码,与出来一般是UTF-8的.有时候也需要转化成 GB18030 才能兼容 WINDOWS 系统.


额,,,还是linux好~
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics