Phá vỡ chuỗi dài trên nhiều dòng trong Ruby mà không tước dòng mới


221

Gần đây chúng tôi đã quyết định công việc của tôi với một hướng dẫn phong cách ruby. Một trong những sắc lệnh là không có dòng nào rộng hơn 80 ký tự. Vì đây là dự án Rails, chúng tôi thường có các chuỗi dài hơn một chút - tức là " Người dùng X muốn gửi cho bạn một tin nhắn về Thing Y " không phải lúc nào cũng nằm trong giới hạn kiểu 80 ký tự.

Tôi hiểu có ba cách để có một chuỗi dài nhiều dòng:

  • HEREDOC
  • % Q {}
  • Nối chuỗi thực tế.

Tuy nhiên, tất cả các trường hợp này kết thúc bằng nhiều chu kỳ tính toán hơn, điều này có vẻ ngớ ngẩn. Chuỗi nối rõ ràng, nhưng cho HEREDOC%Qtôi phải loại bỏ các dòng mới, thông qua một cái gì đó như .gsub(/\n$/, '').

Có một cách cú pháp thuần túy để làm điều này, tương đương với việc chỉ có toàn bộ chuỗi trên một dòng? Rõ ràng mục tiêu là không dành thêm bất kỳ chu kỳ nào chỉ vì tôi muốn mã của mình dễ đọc hơn một chút. (Vâng, tôi nhận ra rằng bạn phải thực hiện sự đánh đổi đó rất nhiều ... nhưng đối với độ dài chuỗi, điều này có vẻ ngớ ngẩn.)

Cập nhật: Dấu gạch chéo ngược không chính xác những gì tôi muốn vì bạn mất thụt lề, điều này thực sự ảnh hưởng đến phong cách / khả năng đọc.

Thí dụ:

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

Tôi thấy ở trên một chút khó đọc.

EDIT : Tôi đã thêm một câu trả lời dưới đây; Ba năm sau, chúng ta có một di sản nguệch ngoạc.


Nó có thể là giá trị của bạn trong khi yếu tố ra các chuỗi.
Cheezmeister


Không rõ liệu bạn có muốn giữ các \nký tự dòng mới hay không. Câu trả lời hàng đầu không giữ được họ, nhưng câu trả lời của bạn thì không. Câu hỏi cho biết "không tước bỏ dòng mới", mô tả nói "[...] Tôi phải loại bỏ dòng mới."
Bryan Dimas

Câu trả lời:


432

Có lẽ đây là những gì bạn đang tìm kiếm?

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

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

4
Huh. Vâng, đó là khá hoàn hảo. đó thực sự là làm một concatenate dưới mui xe? (ẩn a +?)
chug2k

13
Tôi khá chắc chắn rằng nó không phải; Tôi đã thử cả Chuỗi không xác định và xác định lại Chuỗi # + và dường như không có gì được gửi ở đó.
Jessehz

Ngoài ra, đặt các chuỗi cạnh nhau trên cùng một dòng cũng hoạt động, nhưng điều đó không hữu ích.
Jessehz

3
Tôi cũng thích giải pháp của Emily. Nhưng vì một số lý do, tôi cảm thấy thoải mái hơn với điều này bởi vì khoảng trắng hàng đầu trên các dòng sau có thể được thụt vào mà không cần đoán chính mình.
Amin Ariana

5
Kết nối lại, kiểm tra câu trả lời của Amadan cho câu hỏi liên quan này . Anh ta sử dụng mã byte để chứng minh rằng nó không phải là chuỗi nối mà chỉ coi chúng là một chuỗi dài.
Tom Hundt

55

Bạn có thể sử dụng \để chỉ ra rằng bất kỳ dòng Ruby nào tiếp tục trên dòng tiếp theo. Điều này cũng hoạt động với chuỗi:

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

puts string.inspect

sẽ xuất "this is a string that spans lines"


11
Huh. điều đó khá đơn giản tốt, có lẽ quá nhiều để hỏi, nhưng tôi không thể thụt dòng tiếp theo. Sẽ thật lý tưởng nếu tôi có thể ghép nó với dấu bằng.
chug2k

5
Lưu ý: bạn không thể có bất kỳ khoảng trắng nào sau dấu gạch chéo ngược đó. Nó phải là nhân vật cuối cùng.
Julian Mann

3
Xem câu trả lời của @Jliehz. Cách để có mã được định dạng độc đáo với thụt lề thích hợp là đặt từng dòng trong dấu ngoặc kép.
ngày

36

Ba năm sau, giờ đây đã có một giải pháp trong Ruby 2.3: The heriggly squiggly.

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

Liên kết bài đăng trên blog: https://infinum.co/the-capsized-eight/articles/multiline-strings-ruby-2-3-0-the-squiggly-heredoc

Việc thụt dòng của dòng thụt lề ít nhất sẽ bị xóa khỏi mỗi dòng của nội dung.


29
Đối với bất cứ ai khác tự hỏi: <<~HEREDOCgiữ các ký tự dòng mới, nó chỉ là sự thụt lùi. Ví dụ:line 1\nline 2\nline 3\n
Bryan Dimas

1
Tước dòng mới vẫn sẽ yêu cầu tính toán thêm, tuy nhiên, điều mà OP ngụ ý là không mong muốn.
henrebotha

1
@henrebotha Có, nhưng OP nói rõ hơn rằng họ muốn "tương đương với việc chỉ có toàn bộ chuỗi trên một dòng", điều này sẽ không yêu cầu dòng mới.
Nick

Vì vậy, bạn đã tuyên bố rõ ràng trong câu hỏi của bạn rằng bạn không muốn sử dụng một di sản và phải loại bỏ các dòng mới. Câu trả lời của bạn ở đây sử dụng một di sản và yêu cầu "xử lý hậu kỳ" mà bạn muốn tránh.
lamont

17

Tôi đã gặp vấn đề này khi tôi cố gắng viết một url rất dài, các công việc sau đây.

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

Lưu ý, không được có bất kỳ dòng mới, khoảng trắng nào khi chuỗi url được hình thành. Nếu bạn muốn có dòng mới, thì hãy sử dụng HEREDOC.

Ở đây bạn có sự thụt vào để dễ đọc, dễ sửa đổi, không có dấu ngoặc kép và dấu gạch chéo ngược trên mỗi dòng. Chi phí tham gia các chuỗi nên không đáng kể.


10

Tôi đã sửa đổi câu trả lời của Zack vì tôi muốn có khoảng trắng và phép nội suy nhưng không phải là dòng mới và được sử dụng:

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

nơi name = 'fred'này sản xuấtIt's a nice day "fred" for a walk!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.