【问题标题】:Breaking up long strings on multiple lines in Ruby without stripping newlines在 Ruby 中拆分多行的长字符串而不去除换行符
【发布时间】:2012-05-18 08:11:59
【问题描述】:

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

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

  • HEREDOC
  • %Q{}
  • 实际的字符串连接。

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

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

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

例子:

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

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

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

【问题讨论】:

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

标签: ruby-on-rails ruby


【解决方案1】:

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

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

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

【讨论】:

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

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

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

puts string.inspect

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

【讨论】:

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

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

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

【讨论】:

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

当我尝试编写一个很长的 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。

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

【讨论】:

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

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

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

name = 'fred' 在哪里产生It's a nice day "fred" for a walk!

【讨论】:

    【解决方案6】:

    这是一个非常古老的问题,但问题似乎仍然存在,这里有一个更新的答案。由于原始海报表明这是针对 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() 返回字符串,先去掉字符串两端的所有空白,然后将剩余的连续空白组各换成一个空格。

    【讨论】:

      【解决方案7】:

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

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

      结束它看起来像这样:

      %{ Multi-line
         string }.squish
      

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

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

      【讨论】:

        【解决方案8】:

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

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

        【讨论】:

          猜你喜欢
          • 2015-08-09
          • 2014-02-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-12
          • 1970-01-01
          • 1970-01-01
          • 2020-10-14
          相关资源
          最近更新 更多