ruby on rails - ¿Cómo reemplazo los caracteres latinos acentuados en Ruby?
encoding ruby (15)
Convierta el texto a la forma D de normalización, elimine todos los puntos de código con la marca no espaciadora de categoría Unicode (Mn) y conviértalo de nuevo a la forma de normalización C. Esto eliminará todos los signos diacríticos y su problema se reducirá a una búsqueda que no distingue entre mayúsculas y minúsculas.
Consulte http://www.siao2.com/2005/02/19/376617.aspx y http://www.siao2.com/2007/05/14/2629747.aspx para obtener más detalles.
Tengo un modelo de ActiveRecord
, Foo
, que tiene un campo de name
. Me gustaría que los usuarios puedan buscar por nombre, pero me gustaría que la búsqueda ignore mayúsculas y minúsculas y acentos. Por lo tanto, también estoy almacenando un campo canonical_name
contra el cual buscar:
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
Necesito completar el "algo aquí" para reemplazar los caracteres acentuados. ¿Hay algo mejor que
x.downcase.gsub(/[àáâãäå]/,''a'').gsub(/æ/,''ae'').gsub(/ç/, ''c'').gsub(/[èéêë]/,''e'')....
Y, para el caso, dado que no estoy en Ruby 1.9, no puedo poner esos literales Unicode en mi código. Las expresiones regulares reales se verán mucho más feas.
Creo que tal vez no realmente qué ir por ese camino. Si se está desarrollando para un mercado que tiene este tipo de letras, sus usuarios probablemente pensarán que es una especie de ... pip . Porque ''å'' ni siquiera está cerca de ''a'' en ningún sentido para un usuario. Tome un camino diferente y lea acerca de la búsqueda de una manera no ascii. Este es solo uno de esos casos que alguien inventó unicode y collation .
Un PD muy tarde :
http://www.w3.org/International/wiki/Case_folding http://www.w3.org/TR/charmod-norm/#sec-WhyNormalization
Además de eso, no tengo ninguna forma de que el enlace a la intercalación vaya a una página msdn, pero la dejo ahí. Debería haber sido http://www.unicode.org/reports/tr10/
Descompón la cuerda y quita las marcas que no estén espaciadas .
irb -ractive_support/all
> "àáâãäå".mb_chars.normalize(:kd).gsub(//p{Mn}/, '''')
aaaaaa
También puede necesitar esto si se usa en un archivo .rb.
# coding: utf-8
la parte normalize(:kd)
divide aquí diacriticals cuando sea posible (por ejemplo, el carácter individual "n con tilda" se divide en una n seguida de un carácter gsub
combinada diacrítica), y la parte gsub
luego elimina todos los caracteres diacríticos.
He intentado muchos de estos enfoques pero no estaban logrando uno o varios de estos requisitos:
- Respetar espacios
- Respetar el carácter ''ñ''
- Caso de respeto (sé que no es un requisito para la pregunta original, pero no es difícil mover una cadena a un nivel bajo )
Ha sido esto:
# coding: utf-8
string.tr(
"ÀÁÂÃÄÅàáâãäåĀāĂ㥹ÇçĆćĈĉĊċČčÐðĎďĐđÈÉÊËèéêëĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħÌÍÎÏìíîïĨĩĪīĬĭĮįİıĴĵĶķĸĹĺĻļĽľĿŀŁłÑñŃńŅņŇňʼnŊŋÒÓÔÕÖØòóôõöøŌōŎŏŐőŔŕŖŗŘřŚśŜŝŞşŠšſŢţŤťŦŧÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųŴŵÝýÿŶŷŸŹźŻżŽž",
"AAAAAAaaaaaaAaAaAaCcCcCcCcCcDdDdDdEEEEeeeeEeEeEeEeEeGgGgGgGgHhHhIIIIiiiiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnNnnNnOOOOOOooooooOoOoOoRrRrRrSsSsSsSssTtTtTtUUUUuuuuUuUuUuUuUuUuWwYyyYyYZzZzZz"
)
Tienes que modificar un poco la lista de caracteres para respetar el carácter ''ñ'' pero es un trabajo fácil.
La clave es usar dos columnas en su base de datos: canonical_text
y original_text
. Use original_text
para mostrar y canonical_text
para búsquedas. De esta forma, si un usuario busca "Visual Cafe", ve el resultado "Visual Café". Si realmente quiere un artículo diferente llamado "Visual Cafe", se puede guardar por separado.
Para obtener los caracteres canonical_text en un archivo fuente Ruby 1.8, haga algo como esto:
register_replacement([0x008A].pack(''U''), ''S'')
Mejor aún es usar I18n:
1.9.3-p392 :001 > require "i18n"
=> false
1.9.3-p392 :002 > I18n.transliterate("Olá Mundo!")
=> "Ola Mundo!"
Mi respuesta: el método de String#parameterize :
"Le cœur de la crémiére".parameterize
=> "le-coeur-de-la-cremiere"
Para programas que no son Rails:
Instale activesupport: gem install activesupport
luego:
require ''active_support/inflector''
"a&]''s--3/014/xC2àáâã3D".parameterize
# => "a-s-3-3d"
Para cualquiera que lea esto que quiera despojar a todos los personajes no ascii, this podría ser útil; utilicé el primer ejemplo con éxito.
Probablemente desee la descomposición Unicode ("NFD"). Después de descomponer la cadena, simplemente filtra todo lo que no esté en [A-Za-z]. æ se descompondrá en "ae", ã en "a ~" (aproximadamente - el diacrítico se convertirá en un carácter separado) por lo que el filtrado deja una aproximación razonable.
Rails ya tiene un built-in para normalizar, solo tiene que usar esto para normalizar su cadena para formar KD y luego eliminar los otros caracteres (es decir, acentos) como este:
>> "àáâãäå".mb_chars.normalize(:kd).gsub(/[^/x00-/x7F]/n,'''').downcase.to_s
=> "aaaaaa"
Tuve problemas para obtener la solución foo.mb_chars.normalize (: kd) .gsub (/ [^ / x00- / x7F] / n, ''''). Downcase.to_s para que funcione. No estoy usando Rails y hubo algún conflicto con mis versiones de active support / ruby que no pude llegar al final.
Usar la gema ruby-unf parece ser un buen sustituto:
require ''unf''
foo.to_nfd.gsub(/[^/x00-/x7F]/n,'''').downcase
Por lo que puedo decir, esto hace lo mismo que .mb_chars.normalize (: kd). ¿Es esto correcto? ¡Gracias!
iconv:
http://groups.google.com/group/ruby-talk-google/browse_frm/thread/8064dcac15d688ce ?
=============
un módulo perl que no puedo entender:
http://www.ahinea.com/en/tech/accented-translate.html
============
fuerza bruta (¡hay muchas criaturas htosas !:
http://projects.jkraemer.net/acts_as_ferret/wiki#UTF-8support
jaja ... acabo de probar esto ... y está funcionando ... iam todavía no estoy muy seguro de por qué ... pero cuando uso estas 4 líneas de código:
- str = str.gsub (/ [^ a-zA-Z0-9] /, "")
- str = str.gsub (/ [] + /, "")
- str = str.gsub (/ /, "-")
- str = str.downcase
elimina automáticamente cualquier acento de los nombres de archivo ... que estaba tratando de eliminar (acentuación de los nombres de los archivos y renombrarlos) espero que haya ayudado :)
ActiveSupport::Inflector.transliterate
(requiere Rails 2.2.1+ y Ruby 1.9 o 1.8.7)
ejemplo:
>> ActiveSupport::Inflector.transliterate("àáâãäå").to_s => "aaaaaa"
Esto supone que usa Rails.
"anything".parameterize.underscore.humanize.downcase
Teniendo en cuenta sus requisitos, esto es probablemente lo que haría ... Creo que es limpio, simple y se mantendrá actualizado en versiones futuras de Rails y Ruby.
Actualización: dgilperez señaló que parameterize
toma un argumento de separación, por lo que "anything".parameterize(" ")
(obsoleto) o "anything".parameterize(separator: " ")
es más corto y más limpio.