如何在Ruby中replace重音拉丁字符?
我有一个ActiveRecord
模型, Foo
,它有一个name
字段。 我希望用户能够按名称search,但我希望search忽略大小写和任何重音符号。 因此,我还存储了一个canonical_name
字段来search:
class Foo validates_presence_of :name before_validate :set_canonical_name private def set_canonical_name self.canonical_name ||= canonicalize(self.name) if self.name end def canonicalize(x) x.downcase. # something here end end
我需要填写“这里的东西”,以取代重音字符。 还有比这更好的吗?
x.downcase.gsub(/[àáâãäå]/,'a').gsub(/æ/,'ae').gsub(/ç/, 'c').gsub(/[èéêë]/,'e')....
而且,对于这个问题,因为我不在Ruby 1.9上,所以我不能把这些Unicode文字放在我的代码中。 实际的正则expression式看起来更丑陋。
Rails已经有一个内置的标准化,你只需要使用这个标准化你的string来形成KD,然后删除其他字符(即重音符号),如下所示:
>> "àáâãäå".mb_chars.normalize(:kd).gsub(/[^\x00-\x7F]/n,'').downcase.to_s => "aaaaaa"
ActiveSupport::Inflector.transliterate
(需要Rails 2.2.1+和Ruby 1.9或1.8.7)
例:
>> ActiveSupport::Inflector.transliterate("àáâãäå").to_s => "aaaaaa"
更好的是使用I18n:
1.9.3-p392 :001 > require "i18n" => false 1.9.3-p392 :002 > I18n.transliterate("Olá Mundo!") => "Ola Mundo!"
我已经尝试了很多这种方法,但他们没有达到这些要求中的一个或几个:
- 尊重空间
- 尊重''字符
- 尊重案件(我知道是不是原来的问题的要求,但不难将string移动到小写 )
一直是这样的:
# coding: utf-8 string.tr( "ÀÁÂÃÄÅàáâãäåĀāĂ㥹ÇçĆćĈĉĊċČčÐðĎďĐđÈÉÊËèéêëĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħÌÍÎÏìíîïĨĩĪīĬĭĮįİıĴĵĶķĸĹĺĻļĽľĿŀŁłÑñŃńŅņŇňʼnŊŋÒÓÔÕÖØòóôõöøŌōŎŏŐőŔŕŖŗŘřŚśŜŝŞşŠšſŢţŤťŦŧÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųŴŵÝýÿŶŷŸŹźŻżŽž", "AAAAAAaaaaaaAaAaAaCcCcCcCcCcDdDdDdEEEEeeeeEeEeEeEeEeGgGgGgGgHhHhIIIIiiiiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnNnnNnOOOOOOooooooOoOoOoRrRrRrSsSsSsSssTtTtTtUUUUuuuuUuUuUuUuUuUuWwYyyYyYZzZzZz" )
你必须修改一些字符列表来尊重'ñ'字符,但是很容易。
我想你可能真的不知道该怎么走。 如果你正在开发一个有这种信件的市场,你的用户可能会认为你是一种… 点子 。 因为对于用户来说,''甚至不是接近于'a'。 采取不同的道路,并阅读有关search非ascii的方式。 这只是有人发明unicode和整理的情况之一 。
非常晚PS :
http://www.w3.org/International/wiki/Case_folding http://www.w3.org/TR/charmod-norm/#sec-WhyNormalization
除此之外,我没有ide的方式链接到整理去msdn页面,但我离开它。 它应该是http://www.unicode.org/reports/tr10/
我的回答: String#parameterize方法:
"Le cœur de la crémiére".parameterize => "le-coeur-de-la-cremiere"
对于非Rails程序:
安装activesupport: gem install activesupport
然后:
require 'active_support/inflector' "a&]'s--3\014\xC2àáâã3D".parameterize # => "as-3-3d"
分解string并从中删除非间距标记 。
irb -ractive_support/all > "àáâãäå".mb_chars.normalize(:kd).gsub(/\p{Mn}/, '') aaaaaa
如果在.rb文件中使用,您可能还需要这个。
# coding: utf-8
在这里, normalize(:kd)
部分在可能的情况下分开变音符号(例如:“n with tilda”单个字符被分割成n,然后是组合变音符tilda字符),然后gsub
部分删除所有变音符号。
这假定你使用Rails。
"anything".parameterize.underscore.humanize.downcase
根据你的要求,这可能是我会做的…我认为它是整洁,简单,并保持最新的Rails和Ruby的未来版本。
更新:dgilperez指出parameterize
需要一个分隔符参数,所以"anything".parameterize(" ")
(不推荐)或"anything".parameterize(separator: " ")
更短,更干净。
将文本转换为标准化格式D,使用unicode类别非间距标记(Mn)删除所有的代码点,并将其转换回标准化格式C.这将删除所有的变音符号,并将您的问题简化为不区分大小写的search。
详细信息请参见http://www.siao2.com/2005/02/19/376617.aspx和http://www.siao2.com/2007/05/14/2629747.aspx 。
关键是在数据库中使用两列: canonical_text
和original_text
。 使用original_text
进行显示,使用canonical_text
进行search。 这样,如果用户search“视觉咖啡馆”,她看到“视觉咖啡厅”结果。 如果她真的想要一个名为“Visual Cafe”的不同的项目,可以单独保存。
要获得Ruby 1.8源文件中的canonical_text字符,请执行如下操作:
register_replacement([0x008A].pack('U'), 'S')
你可能想要Unicode分解(“NFD”)。 分解string后,只需过滤掉[A-Za-z]中的任何内容。 将分解为“ae”,“a〜”(大约 – 分隔符将成为一个单独的字符),所以过滤留下合理的近似值。
的iconv:
http://groups.google.com/group/ruby-talk-google/browse_frm/thread/8064dcac15d688ce ?
=============
一个perl模块,我不明白:
http://www.ahinea.com/en/tech/accented-translate.html
============
蛮力(有很多htose小动物!:
http://projects.jkraemer.net/acts_as_ferret/wiki#UTF-8support
对于任何读这个想要去掉所有非ASCII字符的人来说, 这可能是有用的,我成功地使用了第一个例子。
我有问题得到foo.mb_chars.normalize(:kd).gsub(/ [^ \ x00- \ x7F] / n,'')。downcase.to_s解决scheme的工作。 我没有使用Rails,与我的主动支持/ruby版本有一些冲突,我无法理解。
使用ruby-unfgem似乎是一个很好的替代品:
require 'unf' foo.to_nfd.gsub(/[^\x00-\x7F]/n,'').downcase
据我所知,这和.mb_chars.normalize(:kd)是一样的。 它是否正确? 谢谢!
大声笑..我刚试了这个..它是工作..我还是不太确定为什么..但是当我使用这4行代码:
- str = str.gsub(/ [^ a-zA-Z0-9] /,“”)
- str = str.gsub(/ [] + /,“”)
- str = str.gsub(/ /,“ – ”)
- str = str.downcase
它自动从文件名删除任何口音..我试图删除(口音从文件名和重命名比)希望它帮助:)