Conversión de mayúsculas y minúsculas en guiones bajos


232

¿Hay alguna función lista que convierta las cadenas de mayúsculas y minúsculas en cadenas separadas por subrayado?

Quiero algo como esto:

"CamelCaseString".to_underscore      

para devolver "camel_case_string".

...


43
FYI: en minúsculas y subrayado se llama "oficialmente" caso de serpiente
Andrew

3
Es extraño ver "oficialmente" entre comillas, y sin embargo, esa es la mejor manera de describirlo.
stevenspiel

Por alguna razón veo que falta el método snakecase. Rieles 4.
Abram

Respuestas:


363

ActiveSupport de Rails agrega guión bajo a la cadena usando lo siguiente:

class String
  def underscore
    self.gsub(/::/, '/').
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
    gsub(/([a-z\d])([A-Z])/,'\1_\2').
    tr("-", "_").
    downcase
  end
end

Entonces puedes hacer cosas divertidas:

"CamelCase".underscore
=> "camel_case"

55
Si cambia tr("-","_")a tr("- ","_")(espacio agregado al primer parámetro), esto también convertirá los espacios en guiones bajos. Además, no creo que necesite incluir self., o al menos me funciona en Ruby 1.9.3.
Gus Shortz

66
require 'active_support/core_ext/string'
konsolebox

La función de subrayado Usos activos: github.com/rails/rails/blob/…
GreeKatrina

el guión bajo es un método de Rails no ruby, consulte apidock.com/rails/String/underscore .
S.Yadav

1
@ S.Yadav es cierto, el método es Rails, por lo que no puede llamar al subrayado de forma predeterminada, pero al proporcionar el código utilizado y citando rails como fuente, esta respuesta es buena para ruby, dice que puede incluir rails, o simplemente incluya esta función que el equipo de rails escribió y probó.
Michael Gorman

99

Puedes usar

"CamelCasedName".tableize.singularize

O solo

"CamelCasedName".underscore

Ambas opciones darán lugar "camel_cased_name". Puedes consultar más detalles aquí .


11
Esto es parte de la implementación de ActiveSupport :: Inflector, sin ella, no puede usar esas extensiones de cadena (intente en la consola irb pura: "ThisCamelCaseString" .underscore, luego requiera 'active_support / inflector' e intente nuevamente)
Evgenia Manolova

3
La etiqueta del OP dice "ruby-on-rails"
Julien Lamarche

55

Implementación Ruby de una línea:

class String
   # ruby mutation methods have the expectation to return self if a mutation occurred, nil otherwise. (see http://www.ruby-doc.org/core-1.9.3/String.html#method-i-gsub-21)
   def to_underscore!
     gsub!(/(.)([A-Z])/,'\1_\2')
     downcase!
   end

   def to_underscore
     dup.tap { |s| s.to_underscore! }
   end
end

Entonces "SomeCamelCase".to_underscore # =>"some_camel_case"


2
¿Cómo son las otras soluciones no puro rubí?
jrhicks

Oh, sh ... Gracias. Estaba más interesado en escribir que en leer. Como resultado, los enlaces en Rails me hicieron pensar que esos otros fragmentos son específicos de Rails. Respuesta modificada ...
kirushik

1
Hay otro error en mi edición, y no parece que pueda solucionarlo. Aquí está el código corregido: gist.github.com/4027440
Tim Harper el

66
Es posible que desee considerar en su /([^A-Z])([A-Z]+)/lugar, manejar "ALLCAPS"-> en "allcaps"lugar de"a_ll_ca_ps"
Nevir

44
Eso es en realidad un 10-liner!
kristianp

30

Hay un método incorporado de Rails llamado 'subrayado' que puede usar para este propósito

"CamelCaseString".underscore #=> "camel_case_string" 

El método 'subrayado' generalmente se puede considerar como inverso de 'camelizar'


1
método indefinido 'subrayado' para "...": Cadena
Dorian

55
Es un método ActiveSupport
Dorian

20

Así es como lo hace Rails :

   def underscore(camel_cased_word)
     camel_cased_word.to_s.gsub(/::/, '/').
       gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
       gsub(/([a-z\d])([A-Z])/,'\1_\2').
       tr("-", "_").
       downcase
   end

1
Es mejor tener el operando como argumento de método en lugar de invadir la clase String central.
Pistos

1
No esté de acuerdo: es mejor que funcione en la clase como debería ser, o de lo contrario tendrá que pegarlo en un módulo y recordar incluirlo donde lo necesite.
Ghoti

1
También este método es parte de las cuerdas de Rails 3 de todos modos :)
Ghoti

2
Si puedo saltar a este debate, es mejor que invada la clase de cadena cuando lo incluya =).
Evan Moran


7

Echa un vistazo a Snakecase de Ruby Facets

Se manejan los siguientes casos, como se ve a continuación:

"SnakeCase".snakecase         #=> "snake_case"
"Snake-Case".snakecase        #=> "snake_case"
"Snake Case".snakecase        #=> "snake_case"
"Snake  -  Case".snakecase    #=> "snake_case"

De: https://github.com/rubyworks/facets/blob/master/lib/core/facets/string/snakecase.rb

class String

  # Underscore a string such that camelcase, dashes and spaces are
  # replaced by underscores. This is the reverse of {#camelcase},
  # albeit not an exact inverse.
  #
  #   "SnakeCase".snakecase         #=> "snake_case"
  #   "Snake-Case".snakecase        #=> "snake_case"
  #   "Snake Case".snakecase        #=> "snake_case"
  #   "Snake  -  Case".snakecase    #=> "snake_case"
  #
  # Note, this method no longer converts `::` to `/`, in that case
  # use the {#pathize} method instead.

  def snakecase
    #gsub(/::/, '/').
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
    gsub(/([a-z\d])([A-Z])/,'\1_\2').
    tr('-', '_').
    gsub(/\s/, '_').
    gsub(/__+/, '_').
    downcase
  end

  #
  alias_method :underscore, :snakecase

  # TODO: Add *separators to #snakecase, like camelcase.

end

No funciona con una cadena con caracteres especiales. Ej:"Dumb Penguin's Egg".snakecase # => "dumb_penguin's_egg"
khiav reoy

6

Oneliner corto para CamelCases cuando también tiene espacios incluidos (no funciona correctamente si tiene una palabra intermedia con una pequeña letra de inicio):

a = "Test String"
a.gsub(' ', '').underscore

  => "test_string"

1
underscoreno es parte de ruby
dft

4

En caso de que alguien busque un caso en el que necesite aplicar un guión bajo a una cadena con espacios y desee convertirlos también en guiones bajos, puede usar algo como esto

'your String will be converted To underscore'.parameterize.underscore
#your_string_will_be_converted_to_underscore

O simplemente use .parameterize ('_') pero tenga en cuenta que este está en desuso

'your String will be converted To underscore'.parameterize('_')
#your_string_will_be_converted_to_underscore

1

Me gustaría esto:

class String

  # \n returns the capture group of "n" index
  def snikize
    self.gsub(/::/, '/')
    .gsub(/([a-z\d])([A-Z])/, "\1_\2")
    .downcase
  end

  # or

  def snikize
    self.gsub(/::/, '/')
    .gsub(/([a-z\d])([A-Z])/) do
      "#{$1}_#{$2}"
    end
    .downcase
  end

end

Mono parche de Stringclase. Hay clases que comienzan con dos o más letras en mayúsculas.


Necesitas cambiar "\1_\2"a, de lo '\1_\2'contrario, terminarás en "came\u0001_\u0002ase"lugar de a "camel_case"partir de Ruby 2.5 ... tal vez otros también.
6 pies Dan
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.