ChatGPT解决这个技术问题 Extra ChatGPT

在 Ruby 中拆分多行的长字符串而不去除换行符

我们最近决定在我的工作中编写一份 ruby 风格指南。其中一项法令是任何行不得超过 80 个字符。由于这是一个Rails 项目,我们经常有稍长的字符串——例如“用户X 想向您发送关于Thing Y 的消息”,这并不总是符合80 个字符的样式限制。

我知道有三种方法可以使长字符串跨越多行:

赫雷多克

%Q{}

实际的字符串连接。

然而,所有这些情况最终都会花费更多的计算周期,这似乎很愚蠢。字符串连接很明显,但是对于 HEREDOC%Q,我必须通过 .gsub(/\n$/, '') 之类的东西去掉换行符。

有没有一种纯粹的语法方法来做到这一点,这相当于将整个字符串放在一行上?显然,目标是不要仅仅因为我希望我的代码更具可读性而花费任何额外的周期。 (是的,我意识到你必须做出很多权衡......但是对于字符串长度,这似乎很愚蠢。)

更新:反斜杠并不是我想要的,因为你失去了缩进,这真的影响了风格/可读性。

例子:

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

我觉得上面的内容有点难以阅读。

编辑:我在下面添加了一个答案;三年后,我们现在有了波浪形的heredoc。

将这些字符串分解出来可能是值得的。
👎🏼 是否要保留 \n 个换行符尚不清楚。最佳答案并没有保留它们 - 但您的答案却保留了它们。问题说“不删除换行符” - 但描述说“[...]我必须删除换行符。”

J
Jessehz

也许这就是你要找的东西?

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

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

嗯。是的,这非常完美。这实际上是在幕后进行连接吗? (隐藏一个+?)
我相当确定它不是;我尝试了 undef'ing 和重新定义 String#+ 并且似乎没有任何东西被发送到那里。
此外,将字符串彼此相邻放在同一行上也可以,但这不是很有用。
我也喜欢 Emily 的解决方案。但由于某种原因,我对这个更舒服,因为以下行中的前导空格可以缩进而无需事后猜测。
重新连接,查看 Amadan 对 this related question 的回答。他使用字节码来证明它不是连接字符串,而是将它们视为一个长字符串。
E
Emily

您可以使用 \ 指示任何 Ruby 行在下一行继续。这也适用于字符串:

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

puts string.inspect

将输出 "this is a string that spans lines"


嗯。这很简单。好吧,这可能问得太多了,但我不能缩进下一行。如果我可以将它与等号匹配,那将是理想的。
注意:反斜杠后不能有任何空格。它必须是最后一个字符。
请参阅@Jessehz 的答案。使用适当缩进的格式良好的代码的方法是将每一行放在引号中。
c
chug2k

三年后,现在在 Ruby 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

缩进最小的行的缩进将从内容的每一行中删除。


对于其他想知道的人:<<~HEREDOC 保留换行符,它只是消除了缩进。例如line 1\nline 2\nline 3\n
但是,去除换行符仍然需要额外的计算,而 OP 所暗示的这种计算是不可取的。
@henrebotha是的,但是OP更明确地说他们想要“相当于将整个字符串放在一行上”,这不需要换行符。
所以你在你的问题中明确表示你不想使用heredoc并且必须去掉换行符。您在此处的回答使用了heredoc,并且需要您想要避免的“后处理”。
Z
Zack Xu

当我尝试写一个很长的网址时,我遇到了这个问题,下面的作品。

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。

在这里,您可以缩进以提高可读性、易于修改,并且每行都没有繁琐的引号和反斜杠。加入字符串的成本应该可以忽略不计。


您将如何在这种类型的数组中使用变量?
我相信这个不支持插值,类似于单引号的工作方式。您必须使用大写 W 然后像在字符串中一样插入
如果需要插值,只需使用 %W 大写 w
这不能回答 OP 的“无额外计算”要求。 .join 将连接字符串。
i
iheggie

我修改了 Zack 的答案,因为我想要空格和插值而不是换行符并使用:

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

其中 name = 'fred' 这会产生 It's a nice day "fred" for a walk!


g
geoff

到目前为止,这是一个非常古老的问题,但由于问题似乎仍然出现,这里有一个更新的答案。由于原始海报表明这是针对 Rails 项目的,因此您可以查看 Rails 的 String inflections 寻求帮助。

my_long_string = <<-STRING
 hello
    there
 multiline
      multiindented string
STRING

=> " hello\n    there\n multiline\n      multiindented string\n"

输入 squish 方法。

my_long_string = <<-STRING.squish
 so
    long
 multiline
      multiindented string
STRING

=> "so long multiline multiindented string"

根据文档 -

squish() 返回字符串,首先删除字符串两端的所有空格,然后将剩余的连续空格组分别更改为一个空格。


v
viktorianer

Rails 中的 Squish 可以满足您的需求。

https://apidock.com/rails/String/squish

结束它看起来像这样:

%{ Multi-line
   string }.squish

因为你在 Ruby 中需要它,所以看看 Rails 代码:

%{ Multi-line
   string }
  .gsub!(/[[:space:]]+/, " ")
  .strip!

M
Matias Korhonen

您可以连接多个拆分为多行的字符串:

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