在ruby中将骆驼案转换为下划线案


232

是否有任何就绪函数可以将驼峰式字符串转换为下划线分隔的字符串?

我想要这样的东西:

"CamelCaseString".to_underscore      

返回“ camel_case_string”。

...


43
仅供参考:小写和强调的“正式”称为蛇案
安德鲁

3
看到“正式”用引号是很奇怪的,但是,这是描述它的最佳方式。
stevenspiel 2014年

由于某种原因,我看到了snakecase方法的缺失。Rails 4.
Abram

Answers:


362

Rails的ActiveSupport 使用以下命令在字符串中添加下划线:

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

然后,您可以做一些有趣的事情:

"CamelCase".underscore
=> "camel_case"

5
如果更改tr("-","_")tr("- ","_")(在第一个参数中添加了空格),这也会将空格变为下划线。另外,我认为您甚至不需要包含self.,或者至少在Ruby 1.9.3下它对我有用。
Gus Shortz

6
require 'active_support/core_ext/string'
konsolebox '16

Active使用的下划线功能:github.com/rails/rails/blob/…–
GreeKatrina

下划线是Rails的方法,不是ruby,请参阅apidock.com/rails/String/underscore
S.Yadav

1
@ S.Yadav是的,该方法是Rails,因此默认情况下您不能调用下划线,但是通过提供使用的代码并引用rails作为源,此答案对于ruby是一个很好的选择,它说您可以包含rails,或者包括Rails团队编写和测试的功能。
Michael Gorman

99

您可以使用

"CamelCasedName".tableize.singularize

要不就

"CamelCasedName".underscore

两种选择都会产生效果"camel_cased_name"。您可以在此处查看更多详细信息。


11
这是ActiveSupport :: Inflector的实现的一部分,没有它,您将无法使用这些String扩展名(在纯irb控制台中尝试:“ ThisCamelCaseString”。下划线,然后需要'active_support / inflector',然后重试)
Evgenia Manolova

3
OP的标签上确实标有“ ruby​​-on-rails”
朱利安·拉马尔什

55

一线式Ruby实现:

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

所以 "SomeCamelCase".to_underscore # =>"some_camel_case"


2
其他解决方案不是纯红宝石吗?
jrhicks,2009年

哦,嘘...谢谢-我对写作比对阅读更感兴趣。因此,Rails上的链接使我认为其他片段是特定于Rails的。答案已更改...
kirushik

1
我的编辑中还有另一个错误,但似乎无法修复。这是更正后的代码:gist.github.com/4027440
Tim Harper

6
您可能需要考虑/([^A-Z])([A-Z]+)/处理"ALLCAPS"-> "allcaps"而不是"a_ll_ca_ps"
Nevir

4
那实际上是10班轮!
kristianp '16

30

有一个称为“下划线”的Rails内置方法可用于此目的。

"CamelCaseString".underscore #=> "camel_case_string" 

“下划线”方法通常可以视为“驼峰式”的反函数


1
未定义的方法'underscore'for“ ...”:String
Dorian

5
这是一种ActiveSupport方法
Dorian

20

这是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
最好将操作数作为方法参数,而不要入侵核心String类。
Pistos

1
不同意-最好让它像应该的那样在类上运行,否则您将不得不将其粘贴在模块中,并记住在需要时将其包括在内。
Ghoti

1
同样,此方法还是Rails 3字符串的一部分:)
Ghoti

2
如果我可以在跳转到这个辩论-最好有它侵入串类,当你包括它=)。
埃文·莫兰


7

Ruby Facets中检出蛇壳

处理以下情况,如下所示:

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

来自: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

它不适用于带有特殊字符的字符串。"Dumb Penguin's Egg".snakecase # => "dumb_penguin's_egg"
举例

6

当还包含空格时,用于CamelCases的短oneliner(如果您之间有一个单词且开头字母较小,则无法正常工作):

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

  => "test_string"

1
underscore不是红宝石的一部分
dft19年

4

如果有人在寻找需要将下划线应用于带空格的字符串并将其也转换为下划线的情况,则可以使用类似以下的方式

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

或仅使用.parameterize('_'),但请记住,此参数已被弃用

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

1

我想要这样:

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

String类的猴子补丁。有一些类以两个或多个大写字母开头。


您需要更改"\1_\2"为,'\1_\2'否则最终将使用Ruby 2.5 "came\u0001_\u0002ase"而不是"camel_case"Ruby 2.5 ...也许还有其他版本。
6英尺丹,
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.