18

你如何有一个没有前导空格的多行字符串并且仍然与方法正确对齐?以下是我的一些尝试。正在工作的那个不是很有趣...

module Something
  def welcome
"
Hello

This is an example.  I have to write this multiline string outside the welcome method
indentation in order for it to be properly formatted on screen. :(
"
  end
end

module Something
  def welcome
    "
    Hello

    This is an example.  I am inside welcome method indentation but for some reason
    I am not working...
    ".ljust(12)
  end
end

module Something
  def welcome
    "Hello\n\n"+
    "This is an example.  I am inside welcome method indentation and properly"+
    "formatted but isn't there a better way?"
  end
end

更新

这是ruby​​ 样式指南中的一种方法

code = <<-END.gsub(/^\s+\|/, '')
  |def test
  |  some_method
  |  other_method
  |end
END
# => "def test\n  some_method\n  other_method\nend\n"
4

4 回答 4

45

从 Ruby 2.3.0 开始,有一个内置方法:[ <<~]

indented = 
<<-EOS
  Hello

  This is an example. I have to write this multiline string outside the welcome method indentation in order for it to be properly formatted on screen. :(
EOS

unindented =
<<~EOS
  Hello

  This is an example. I have to write this multiline string outside the welcome method indentation in order for it to be properly formatted on screen. :(
EOS

puts indented #=>

  Hello

  This is an example. I have to write this multiline string outside the welcome method indentation in order for it to be properly formatted on screen. :(

puts unindented #=>

Hello

This is an example. I have to write this multiline string outside the welcome method indentation in order for it to be properly formatted on screen. :(

Ruby 2.3 中的多行字符串 - 波浪形的heredoc

于 2017-01-13T15:50:02.190 回答
4

RubyTapas Episode 249中,Avdi Grimm 描述了一种从多行字符串中去除前导空格的技术:

def unindent(s)
  s.gsub(/^#{s.scan(/^[ \t]+(?=\S)/).min}/, '')
end

它与该问题的其他现有解决方案的行为兼容,例如ActiveSupport / Rails 中的String#strip_heredoc或独立的unindent gem

您可以将此方法与ruby​​(和许多其他语言)中的特殊语法heredoc一起使用来编写多行字符串。

module Something
  def unindent(s)
    s.gsub(/^#{s.scan(/^[ \t]+(?=\S)/).min}/, '')
  end

  def welcome
    unindent(<<-TEXT)
      Hello

      This is an example. This multiline string works
        - even with deeper nestings...
      All is OK here :)
    TEXT
  end
end
于 2015-11-04T19:19:47.283 回答
2

您可以使用 HEREDOC - http://ruby-doc.org/docs/ruby-doc-bundle/Manual/man-1.4/syntax.html#here_doc - 像这样:

def welcome
  <<-"welcome".strip_heredoc
    "
    Hello

    This is an example.  I have to write this multiline string outside the welcome method indentation in order for it to be properly formatted on screen. :(
    "
  welcome
end

并用于strip_heredoc删除缩进 - http://apidock.com/rails/String/strip_heredoc

笔记:

strip_heredoc仅当您使用 Ruby on Rails(它是 Rails 助手)时才可用。如果您只是在纯 Ruby 中构建它,那么很遗憾strip_heredoc您将无法使用它。:-(

但不要害怕纯粹的 Ruby 用户!您可以简单地从 Rails 中提取源代码,strip_heredoc然后通过重新定义String类将其添加到 Ruby 中。在这种情况下,您也可以随意调用该方法。:-)

像这样:

class String
  def strip_it_real_good
    indent = scan(/^[ \t]*(?=\S)/).min.try(:size) || 0
    gsub(/^[ \t]{#{indent}}/, '')
  end
end

def welcome
  <<-"welcome".strip_it_real_good
    "
    Hello

    This is an example.  I have to write this multiline string outside the welcome method indentation in order for it to be properly formatted on screen. :(
    "
  welcome
end
于 2015-11-04T16:50:34.693 回答
-1

我不确定我是否理解这个问题。这个(纯 Ruby)解决方案能满足您的需求吗?

arr = <<-BITTER_END.split("\n")
  Hello
         Testing, testing.
       I assume the least-indented line is to be left-adjusted and the same amount of leading whitespace is to be removed from all other lines.
BITTER_END
undent = arr.map { |line| line[/^\s*/].size }.min
str = arr.map { |s| s[undent..-1] }.join("\n")

puts str
Hello
     Testing, testing.
   I assume the least-indented line is to be left-adjusted and the same amount of leading whitespace is to be removed from all other lines.
于 2015-11-04T19:18:51.173 回答