ทำลายสตริงที่ยาวในหลายบรรทัดใน Ruby โดยไม่ต้องขึ้นบรรทัดใหม่


221

เมื่อเร็ว ๆ นี้เราตัดสินใจที่จะทำงานกับไกด์สไตล์ทับทิม หนึ่งในสิตที่ไม่ควรมีความกว้างเกิน 80 ตัวอักษร เนื่องจากนี่เป็นโครงการ Rails เรามักจะมีสตริงที่ยาวกว่าเล็กน้อยนั่นคือ " User X ต้องการส่งข้อความเกี่ยวกับ Thing Y " ให้คุณซึ่งไม่เหมาะกับความยาวของอักขระ 80 ตัว

ฉันเข้าใจว่ามีสามวิธีในการใช้สตริงที่มีความยาวหลายบรรทัด:

  • HEREDOC
  • Q% {}
  • การต่อสตริงที่เกิดขึ้นจริง

อย่างไรก็ตามกรณีทั้งหมดนี้จบลงด้วยการคำนวณรอบมากขึ้นซึ่งดูเหมือนว่าโง่ สตริงอย่างเห็นได้ชัด แต่สำหรับHEREDOCและฉันต้องดึงออกจากการขึ้นบรรทัดใหม่ผ่านสิ่งที่ต้องการ%Q.gsub(/\n$/, '')

มีวิธีทางไวยากรณ์ที่บริสุทธิ์ในการทำเช่นนี้ซึ่งเทียบเท่ากับเพียงแค่มีทั้งสายในหนึ่งบรรทัด? เห็นได้ชัดว่าเป้าหมายคือการไม่ใช้รอบพิเศษเพียงเพราะฉันต้องการรหัสของฉันจะอ่านง่ายขึ้นเล็กน้อย (ใช่ฉันรู้ว่าคุณต้องทำให้การแลกเปลี่ยนนั้นมาก ... แต่สำหรับความยาวของสตริงสิ่งนี้ดูเหมือนจะไร้สาระ)

อัปเดต: แบ็กสแลชไม่ได้เป็นอย่างที่ฉันต้องการเพราะคุณเสียการเยื้องซึ่งส่งผลต่อสไตล์ / ความสามารถในการอ่าน

ตัวอย่าง:

if foo
  string = "this is a \  
string that spans lines"  
end

ฉันพบว่าข้างต้นอ่านยากนิดหน่อย

แก้ไข : ฉันเพิ่มคำตอบด้านล่าง; สามปีต่อมาตอนนี้เรามี heredoc อย่างแน่นหนา


มันอาจจะคุ้มค่าที่คุณจะแยกแยะสตริงเหล่านั้นออกไป
Cheezmeister


👎🏼ไม่ชัดเจนว่าคุณต้องการเก็บ\nอักขระบรรทัดใหม่หรือไม่ คำตอบยอดนิยมไม่ได้เก็บไว้ แต่คำตอบของคุณก็คือ คำถามที่ว่า "โดยไม่ต้องขึ้นบรรทัดใหม่" - แต่คำอธิบายบอกว่า "[... ] ฉันต้องตัดบรรทัดใหม่"
ไบรอันดิมัส

คำตอบ:


432

บางทีนี่คือสิ่งที่คุณกำลังมองหา?

string = "line #1"\
         "line #2"\
         "line #3"

p string # => "line #1line #2line #3"

4
ฮะ. ใช่แล้วมันค่อนข้างสมบูรณ์แบบ ที่จริงแล้วการต่อเรียงใต้กระโปรงหน้ารถหรือไม่ (ซ่อนเครื่องหมาย +?)
chug2k

13
ฉันค่อนข้างแน่ใจว่ามันไม่ใช่ ฉันลองทั้งการยกเลิกและการกำหนดค่า String # + อีกครั้งและดูเหมือนว่าจะไม่มีสิ่งใดถูกส่งไปที่นั่น
Jessehz

นอกจากนี้การวางสตริงที่อยู่ติดกันในบรรทัดเดียวกันก็ใช้งานได้เช่นกัน แต่นั่นก็ไม่ได้มีประโยชน์มากนัก
Jessehz

3
ฉันชอบโซลูชันของ Emily ด้วย แต่ด้วยเหตุผลบางอย่างฉันรู้สึกสะดวกสบายกับอันนี้มากขึ้นเพราะนำช่องว่างสีขาวในบรรทัดต่อไปนี้สามารถเยื้องได้โดยไม่ต้องเดาตัวเอง
อามินอาเรียนา

5
การต่อข้อมูลใหม่ให้ตรวจสอบคำตอบของ Amadan สำหรับคำถามที่เกี่ยวข้องนี้ เขาใช้โค้ดไบต์เพื่อพิสูจน์ว่ามันไม่ได้เป็นการเชื่อมโยงสตริง แต่ให้ถือว่ามันเป็นสายยาว ๆ
Tom Hundt

55

คุณสามารถใช้\เพื่อระบุว่าบรรทัดใดของ Ruby ยังคงอยู่ในบรรทัดถัดไป วิธีนี้ใช้ได้กับสตริงด้วย:

string = "this is a \
string that spans lines"

puts string.inspect

จะส่งออก "this is a string that spans lines"


11
ฮะ. นั่นง่ายมาก มันอาจจะมากเกินไปที่จะถาม แต่ฉันไม่สามารถเยื้องบรรทัดถัดไป มันจะเหมาะถ้าฉันสามารถจับคู่กับเครื่องหมายเท่ากับ
chug2k

5
หมายเหตุ: คุณไม่สามารถเว้นวรรคสีขาวหลังจากแบ็กสแลชนั้น มันจะต้องเป็นตัวละครตัวสุดท้าย
Julian Mann

3
ดูคำตอบโดย @Jessehz วิธีที่จะมีรูปแบบรหัสอย่างดีพร้อมการเยื้องที่เหมาะสมคือการใส่แต่ละบรรทัดในเครื่องหมายคำพูด
orrd

36

สามปีต่อมาขณะนี้มีวิธีการแก้ปัญหาในทับทิม 2.3: heredoc ไก่เขี่ย

class Subscription
  def warning_message
    <<~HEREDOC
      Subscription expiring soon!
      Your free trial will expire in #{days_until_expiration} days.
      Please update your billing information.
    HEREDOC
  end
end

ลิงก์โพสต์บล็อก: https://infinum.co/the-capsized-eight/articles/multiline-strings-ruby-2-3-0-the-squiggly-heredoc

การเยื้องของบรรทัดที่เยื้องน้อยที่สุดจะถูกลบออกจากแต่ละบรรทัดของเนื้อหา


29
สำหรับคนอื่นที่สงสัยว่า: <<~HEREDOCรักษาตัวละครขึ้นบรรทัดใหม่มันเป็นเพียงการเยื้องเยื้อง เช่นline 1\nline 2\nline 3\n
ไบรอันดิมัส

1
การขึ้นบรรทัดใหม่จะยังคงต้องใช้การคำนวณพิเศษซึ่งการเรียงลำดับโดยนัยของ OP ไม่พึงปรารถนา
henrebotha

1
@henrebotha ใช่ แต่ OP กล่าวอย่างชัดเจนยิ่งขึ้นว่าพวกเขาต้องการ "เทียบเท่ากับเพียงแค่มีทั้งสายในหนึ่งบรรทัด" ซึ่งจะต้องไม่มีการขึ้นบรรทัดใหม่
นิค

ดังนั้นคุณระบุไว้อย่างชัดเจนในคำถามของคุณว่าคุณไม่ต้องการใช้ heredoc และต้องตัดการขึ้นบรรทัดใหม่ คำตอบของคุณที่นี่ใช้ heredoc และต้องการ "post-processing" ที่คุณต้องการหลีกเลี่ยง
lamont

17

ฉันมีปัญหานี้เมื่อฉันพยายามเขียน URL ที่ยาวมากงานต่อไปนี้

image_url = %w(
    http://minio.127.0.0.1.xip.io:9000/
    bucket29/docs/b7cfab0e-0119-452c-b262-1b78e3fccf38/
    28ed3774-b234-4de2-9a11-7d657707f79c?
    X-Amz-Algorithm=AWS4-HMAC-SHA256&
    X-Amz-Credential=ABABABABABABABABA
    %2Fus-east-1%2Fs3%2Faws4_request&
    X-Amz-Date=20170702T000940Z&
    X-Amz-Expires=3600&X-Amz-SignedHeaders=host&
    X-Amz-Signature=ABABABABABABABABABABAB
    ABABABABABABABABABABABABABABABABABABA
).join

หมายเหตุจะต้องไม่มีการขึ้นบรรทัดใหม่ช่องว่างสีขาวเมื่อมีการสร้างสตริง url หากคุณต้องการบรรทัดใหม่ให้ใช้ HEREDOC

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


10

ฉันแก้ไขคำตอบของ Zack เนื่องจากฉันต้องการช่องว่างและการแก้ไข แต่ไม่ขึ้นบรรทัดใหม่และใช้:

%W[
  It's a nice day "#{name}"
  for a walk!
].join(' ')

ที่name = 'fred'นี้ผลิตIt's a nice day "fred" for a walk!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.