如何去除红宝石中的非ASCII字符

人气:752 发布:2022-10-16 标签: ruby cgi unicode ascii

问题描述

我有一个Ruby CGI(不是Rails),可以从Web表单中挑选照片和标题。我的用户非常热衷于使用智能引号和连字,他们是从其他来源粘贴的。我的Web应用程序不能很好地处理这些非ASCII字符,是否有快速的Ruby字符串操作例程可以清除非ASCII字符?

推荐答案

使用字符串#encode

从Ruby 1.9开始,在字符串编码之间进行转换的官方方式是使用String#encode。

要简单地删除非ASCII字符,您可以执行以下操作:

some_ascii   = "abc"
some_unicode = "áëëçüñżλφθΩ"
more_ascii   = "123ABC"
invalid_byte = "255"

non_ascii_string = [some_ascii, some_unicode, more_ascii, invalid_byte].join

# See String#encode documentation
encoding_options = {
  :invalid           => :replace,  # Replace invalid byte sequences
  :undef             => :replace,  # Replace anything not defined in ASCII
  :replace           => '',        # Use a blank for those replacements
  :universal_newline => true       # Always break lines with 

}

ascii = non_ascii_string.encode(Encoding.find('ASCII'), encoding_options)
puts ascii.inspect
  # => "abce123ABC"

请注意,结果中的前5个字符是"abce1"-丢弃了"á",丢弃了一个"ë",但另一个"ë"似乎已转换为"e"。

原因是有时用Unicode表示相同的书写字符有多种方式。"á"是单个Unicode代码点。第一个"ë"也是。当Ruby在此转换过程中看到它们时,它会丢弃它们。

但是第二个"ë"是两个代码点:一个普通的"e",就像您在ASCII字符串中看到的一样,后面跟着一个"组合变音符号"(this one),意思是"在前一个字符上加一个变音符号"。在Unicode字符串中,这些字符被解释为单个"字素"或可见字符。转换时,Ruby保留纯ASCII"e"并丢弃组合标记。

如果您决定要提供一些特定的替换值,可以这样做:

REPLACEMENTS = { 
  'á' => "a",
  'ë' => 'e',
}

encoding_options = {
  :invalid   => :replace,     # Replace invalid byte sequences
  :replace => "",             # Use a blank for those replacements
  :universal_newline => true, # Always break lines with 

  # For any character that isn't defined in ASCII, run this
  # code to find out how to replace it
  :fallback => lambda { |char|
    # If no replacement is specified, use an empty string
    REPLACEMENTS.fetch(char, "")
  },
}

ascii = non_ascii_string.encode(Encoding.find('ASCII'), encoding_options)
puts ascii.inspect
  #=> "abcaee123ABC"

更新

有些人报告了与:universal_newline选项有关的问题。我断断续续地看到过这种情况,但一直无法找到原因。

当它发生时,我看到Encoding::ConverterNotFoundError: code converter not found (universal_newline)。但是,在一些RVM更新之后,我刚刚在以下Ruby版本下运行了上面的脚本,没有任何问题:

ruby-1.9.2-P290 ruby-1.9.3-p125 ruby-1.9.3-p194 ruby-1.9.3-p362 ruby-2.0.0-预览2 红宝石头(截至2012年12月31日)

鉴于此,它似乎不是Ruby中的弃用特性,甚至不是bug。如果有人知道原因,请发表意见。

528