Ruby方法从UTF-8国际字符中删除重音符号


74

我正在尝试创建字符串的“规范化”副本,以帮助减少数据库中的重复名称。名称包含许多国际字符(即带重音的字母),我想创建一个删除了重音的副本。

我确实遇到了下面的方法,但是无法使其正常工作。我似乎找不到Unicode Hacks插件。

  # Utility method that retursn an ASCIIfied, downcased, and sanitized string.
  # It relies on the Unicode Hacks plugin by means of String#chars. We assume
  # $KCODE is 'u' in environment.rb. By now we support a wide range of latin
  # accented letters, based on the Unicode Character Palette bundled inMacs.
  def self.normalize(str)
     n = str.chars.downcase.strip.to_s
     n.gsub!(/[à áâãäåÄÄ?]/u,    'a')
     n.gsub!(/æ/u,                  'ae')
     n.gsub!(/[ÄÄ?]/u,                'd')
     n.gsub!(/[çÄ?ÄÄ?Ä?]/u,          'c')
     n.gsub!(/[èéêëÄ?Ä?Ä?Ä?Ä?]/u, 'e')
     n.gsub!(/Æ?/u,                   'f')
     n.gsub!(/[ÄÄ?Ä¡Ä£]/u,            'g')
     n.gsub!(/[ĥħ]/,                'h')
     n.gsub!(/[ììíîïīĩĭ]/u,     'i')
     n.gsub!(/[įıijĵ]/u,           'j')
     n.gsub!(/[ķĸ]/u,               'k')
     n.gsub!(/[Å?ľĺļÅ?]/u,         'l')
     n.gsub!(/[ñÅ?Å?Å?Å?Å?]/u,       'n')
     n.gsub!(/[òóôõöøÅÅ?ÅÅ]/u,  'o')
     n.gsub!(/Å?/u,                  'oe')
     n.gsub!(/Ä?/u,                   'q')
     n.gsub!(/[Å?Å?Å?]/u,             'r')
     n.gsub!(/[Å?Å¡Å?ÅÈ?]/u,          's')
     n.gsub!(/[ťţŧÈ?]/u,           't')
     n.gsub!(/[ùúûüūůűŭũų]/u,'u')
     n.gsub!(/ŵ/u,                   'w')
     n.gsub!(/[ýÿŷ]/u,             'y')
     n.gsub!(/[žżź]/u,             'z')
     n.gsub!(/\s+/,                   ' ')
     n.gsub!(/[^\sa-z0-9_-]/,          '')
     n
  end

我是否需要“要求”特定的图书馆/宝石?也许有人可以推荐另一种方法来解决这个问题。

我没有使用Rails,也没有计划这样做。


1
您正在使用哪个红宝石版本?
Huluk


3

我正在使用Ruby 1.9.3,下面将介绍这两种可能的解决方案,我所需要的只是上述方法替换列出的字符,因此,如果这些解决方案能起到很大的作用,并感谢:)
Gus Shortz

我终于找到了一些对Unicode Hack插件的引用(railslodge.com/plugins/316-unicode-hacks),该插件提供了我提到的chars方法所需的normalize方法。但它似乎不再受到支持
Gus Shortz

Answers:


219

我通常使用I18n来处理此问题:

1.9.3p392 :001 > require "i18n"
 => true
1.9.3p392 :002 > I18n.transliterate("Hé les mecs!")
 => "He les mecs!"

3
文档。能够按地区设置音译功能也非常强大。
Paul Fioravanti 2013年

9
对于没有基本拉丁映射的字符(例如汉字),这可能无法满足您的期望。只是将它们变成问号。 (main)> I18n.transliterate("雙屬性集合之空間分群演算法-應用於地理資料") => "?????????????-???????"
大卫

16
只是普通红宝石的注释,如果I18n::InvalidLocale: :en is not a valid locale被抛出,请I18n.available_locales = [:en]在之前使用I18n.transliterate
Alter Lagos

注意:这并不适用于所有情况。示例“BùiViện”被翻译为“ Bui Vi?n”
CHawk 2016年

2
对我(main)> I18n.transliterate "ŠKODA" => "ŠKODA"
Michael

18

到目前为止,以下是我能够完成所需工作的唯一方法:

str.tr(
"ÀÁÂÃÄÅàáâãäåĀāĂ㥹ÇçĆćĈĉĊċČčÐðĎďĐđÈÉÊËèéêëĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħÌÍÎÏìíîïĨĩĪīĬĭĮįİıĴĵĶķĸĹĺĻļĽľĿŀŁłÑñŃńŅņŇňʼnŊŋÒÓÔÕÖØòóôõöøŌōŎŏŐőŔŕŖŗŘřŚśŜŝŞşŠšſŢţŤťŦŧÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųŴŵÝýÿŶŷŸŹźŻżŽž",
"AAAAAAaaaaaaAaAaAaCcCcCcCcCcDdDdDdEEEEeeeeEeEeEeEeEeGgGgGgGgHhHhIIIIiiiiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnNnnNnOOOOOOooooooOoOoOoRrRrRrSsSsSsSssTtTtTtUUUUuuuuUuUuUuUuUuUuWwYyyYyYZzZzZz")

但是使用此方法感觉很“骇人”,我很想找到一种更好的方法。


1
这仅适用于ISO-8859-1。是什么让您认为它适用于UTF-8?
pts 2014年

4
这个适用于UTF-8和ruby 2.2.3,并且完全满足我的需求。虽然缺少一些罗马尼亚字符。我给他们加了广告: string.tr( "ÀÁÂÃÄÅàáâãäåĀāĂ㥹ÇçĆćĈĉĊċČčÐðĎďĐđÈÉÊËèéêëĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħÌÍÎÏìíîïĨĩĪīĬĭĮįİıĴĵĶķĸĹĺĻļĽľĿŀŁłÑñŃńŅņŇňʼnŊŋÒÓÔÕÖØòóôõöøŌōŎŏŐőŔŕŖŗŘřŚśŜŝŞşŠšȘșſŢţŤťŦŧȚțÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųŴŵÝýÿŶŷŸŹźŻżŽž", "AAAAAAaaaaaaAaAaAaCcCcCcCcCcDdDdDdEEEEeeeeEeEeEeEeEeGgGgGgGgHhHhIIIIiiiiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnNnnNnOOOOOOooooooOoOoOoRrRrRrSsSsSsSsSssTtTtTtTtUUUUuuuuUuUuUuUuUuUuWwYyyYyYZzZzZz")
亚历山大

17

所述参数化的方法可以是一个很好的和简单的解决方案,以便使用字符串作为人类可读的标识符,以除去特殊字符:

> "Françoise Isaïe".parameterize
=> "francoise-isaie"

他们没有使用Rails。
snowangel

2

如果您使用滑轨,

my_string = "L'Oréal"
my_string.parameterize(separator=' ')
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.