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".

...

Daniel Cukier
fuente
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"
jrhicks
fuente
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í .

abo-elleef
fuente
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"

Kirushik
fuente
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'

Aaditi Jain
fuente
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
pesto
fuente
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
Abram
fuente
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"
Andres Ehrenpreis
fuente
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
Arman Petrosyan
fuente
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.

rplaurindo
fuente
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