การแปลงเคสอูฐเป็นขีดล่างเป็นทับทิม


232

มีฟังก์ชั่นที่พร้อมใช้งานใดบ้างที่แปลงสตริงตัวอูฐเป็นสตริงที่คั่นด้วยเครื่องหมายขีดล่าง?

ฉันต้องการสิ่งนี้:

"CamelCaseString".to_underscore      

เพื่อส่งคืน "camel_case_string"

...


43
FYI: ตัวพิมพ์เล็กและขีดล่างคือ "อย่างเป็นทางการ" เรียกว่าคดีงู
แอนดรูว์

3
มันแปลกที่เห็น "เป็นทางการ" ในเครื่องหมายคำพูด แต่นั่นเป็นวิธีที่ดีที่สุดในการอธิบาย
stevenspiel

ด้วยเหตุผลบางอย่างฉันเห็นวิธีการ snakecase หายไป Rails 4.
Abram

คำตอบ:


362

ActiveSupport ของ Rails เพิ่มขีดล่างให้กับ String โดยใช้สิ่งต่อไปนี้:

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("- ","_")(เพิ่มช่องว่างใน param แรก) สิ่งนี้จะเปลี่ยนช่องว่างเป็นขีดล่าง นอกจากนี้ฉันไม่คิดว่าคุณจะต้องรวมself.หรืออย่างน้อยก็เหมาะกับฉันภายใต้ Ruby 1.9.3
Gus Shortz

6
require 'active_support/core_ext/string'
konsolebox

ฟังก์ชั่นขีดการใช้งานที่ใช้งานอยู่: github.com/rails/rails/blob/…
GreeKatrina

ขีดเป็นวิธีการของทางรถไฟไม่ทับทิมดูapidock.com/rails/String/underscore
S.Yadav

1
@ S.Yadav จริงวิธีการคือ Rails ดังนั้นคุณไม่สามารถเรียกขีดล่างเป็นค่าเริ่มต้นได้ แต่โดยการให้รหัสที่ใช้และอ้างถึงรางเป็นแหล่งที่มาคำตอบนี้เป็นคำตอบที่ดีสำหรับทับทิมมันบอกว่าคุณสามารถรวมรางหรือเพียง รวมถึงฟังก์ชั่นนี้ที่ทีมรางเขียนและทดสอบ
Michael Gorman

99

คุณสามารถใช้ได้

"CamelCasedName".tableize.singularize

หรือเพียงแค่

"CamelCasedName".underscore

"camel_cased_name"วิธีการทั้งสองตัวเลือกจะให้ผลผลิต คุณสามารถตรวจสอบรายละเอียดเพิ่มเติมมันนี่


11
นี่เป็นส่วนหนึ่งของการใช้งาน ActiveSupport :: Inflector คุณไม่สามารถใช้ส่วนขยายสตริงเหล่านั้นได้ (ลองใช้คอนโซล irb บริสุทธิ์: "ThisCamelCaseString" .underscore จากนั้นต้องใช้ 'active_support / inflector' และลองอีกครั้ง)
Evgenia Manolova

3
ฉลากของ OP พูดว่า "ruby-on-rails"
Julien Lamarche

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

โอ้โห ... ขอบคุณ - ฉันสนใจเขียนมากกว่าการอ่าน ผลที่ตามมา - ลิงก์ใน 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

30

มีวิธีการในตัวรางที่เรียกว่า 'ขีดล่าง' ที่คุณสามารถใช้เพื่อวัตถุประสงค์นี้

"CamelCaseString".underscore #=> "camel_case_string" 

โดยทั่วไปแล้ววิธีการ 'ขีดเส้นใต้' สามารถถือเป็นส่วนกลับของ 'camelize'


1
วิธีที่ไม่ได้กำหนด `ขีดล่าง 'สำหรับ" ... ": 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
ดีกว่าที่จะมีตัวถูกดำเนินการเป็นอาร์กิวเมนต์วิธีแทนที่จะบุกรุกชั้นเรียนสตริงหลัก
Pistos

1
ไม่เห็นด้วย - ดีกว่าที่จะให้มันทำงานในชั้นเรียนอย่างที่ควรจะเป็นหรือไม่เช่นนั้นคุณจะต้องติดมันในโมดูลและอย่าลืมใส่ไว้ในที่ใดก็ตามที่คุณต้องการ
Ghoti

1
นอกจากนี้ยังมีวิธีการนี้เป็นส่วนหนึ่งของทางรถไฟ 3 สายอยู่แล้ว :)
Ghoti

2
ถ้าฉันจะกระโดดเข้าไปในการอภิปรายนี้ - ดีกว่าที่จะให้มันบุกชั้นสตริงเมื่อคุณรวมมัน =)
Evan Moran

7

ผู้รับถูกแปลงเป็นกรณีงู: http://rubydoc.info/gems/extlib/0.9.15/String#snake_case-instance_method

นี่คือไลบรารีการสนับสนุนสำหรับ DataMapper และ Merb ( http://rubygems.org/gems/extlib )

def snake_case
  return downcase if match(/\A[A-Z]+\z/)
  gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
  gsub(/([a-z])([A-Z])/, '\1_\2').
  downcase
end

"FooBar".snake_case           #=> "foo_bar"
"HeadlineCNNNews".snake_case  #=> "headline_cnn_news"
"CNN".snake_case              #=> "cnn"

7

ลองดูSnakecaseจาก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

มันไม่ทำงานกับสตริงที่มีอักขระพิเศษ Ex:"Dumb Penguin's Egg".snakecase # => "dumb_penguin's_egg"
khiav reoy

6

ย่อ oneliner สำหรับ CamelCases เมื่อคุณมีช่องว่างรวมอยู่ด้วย (ทำงานไม่ถูกต้องหากคุณมีคำที่อยู่ระหว่างตัวอักษรขนาดเล็กเริ่มต้น):

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

  => "test_string"

1
underscoreไม่ได้เป็นส่วนหนึ่งของทับทิม
dft

4

ในกรณีที่มีคนมองหากรณีที่เขาต้องการใช้ขีดเส้นใต้กับสตริงที่มีช่องว่างและต้องการแปลงให้เป็นขีดล่างเช่นกันคุณสามารถใช้สิ่งนี้

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

หรือเพียงใช้. พารามิเตอร์ ('_') แต่โปรดจำไว้ว่าอันนี้เลิกใช้แล้ว

'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'มิฉะนั้นคุณจะจบด้วย"came\u0001_\u0002ase"แทนที่จะ"camel_case"เป็น Ruby 2.5 ... อาจจะเป็นคนอื่นเช่นกัน
6ft Dan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.