Ruby:我可以编写没有连接的多行字符串吗?

Zom*_*ies 372 ruby code-formatting

有没有办法让这个看起来好一点?

conn.exec 'select attr1, attr2, attr3, attr4, attr5, attr6, attr7 ' +
          'from table1, table2, table3, etc, etc, etc, etc, etc, ' +
          'where etc etc etc etc etc etc etc etc etc etc etc etc etc'
Run Code Online (Sandbox Code Playgroud)

比如,有没有办法暗示连接?

A. *_*son 558

这个答案有一些东西可以帮助我得到我需要的东西(简单的多行连接没有额外的空格),但由于没有任何实际的答案,我在这里编译它们:

str = 'this is a multi-line string'\
  ' using implicit concatenation'\
  ' to prevent spare \n\'s'

=> "this is a multi-line string using implicit concatenation to eliminate spare
\\n's"
Run Code Online (Sandbox Code Playgroud)

作为奖励,这里是使用有趣的HEREDOC语法的版本(通过此链接):

p <<END_SQL.gsub(/\s+/, " ").strip
SELECT * FROM     users
         ORDER BY users.id DESC
END_SQL
# >> "SELECT * FROM users ORDER BY users.id DESC"
Run Code Online (Sandbox Code Playgroud)

后者主要用于需要处理更灵活的情况.我个人不喜欢它,它把处理放在字符串的一个奇怪的地方(即在它前面,但使用通常后来的实例方法),但它就在那里.请注意,如果要缩进最后一个END_SQL标识符(这很常见,因为这可能在函数或模块中),您将需要使用带连字符的语法(即p <<-END_SQL代替p <<END_SQL).否则,缩进空格会使标识符被解释为字符串的延续.

这不会节省太多打字,但它看起来比使用+标志更好.

编辑:再添加一个:

p %{
SELECT * FROM     users
         ORDER BY users.id DESC
}.gsub(/\s+/, " ").strip
# >> "SELECT * FROM users ORDER BY users.id DESC"
Run Code Online (Sandbox Code Playgroud)

  • 这是一个老问题,但答案要么有错误,要么自那时以来语法发生了变化。`p &lt;&lt;END_SQL` 应该是 `p &lt;&lt;-END_SQL` 否则这就是答案。可选地,您可以使用波浪形的 HEREDOC 运算符“&lt;&lt;~END_SQL”去除前导空格 (5认同)

Mar*_*ers 165

是的,如果您不介意插入额外的换行符:

 conn.exec 'select attr1, attr2, attr3, attr4, attr5, attr6, attr7
            from table1, table2, table3, etc, etc, etc, etc, etc,
            where etc etc etc etc etc etc etc etc etc etc etc etc etc'
Run Code Online (Sandbox Code Playgroud)

或者你可以使用heredoc:

conn.exec <<-eos
   select attr1, attr2, attr3, attr4, attr5, attr6, attr7
   from table1, table2, table3, etc, etc, etc, etc, etc,
   where etc etc etc etc etc etc etc etc etc etc etc etc etc
eos
Run Code Online (Sandbox Code Playgroud)

  • 你也可以使用`%Q(...)` (86认同)
  • 你也可以使用'%(...)` (4认同)
  • @Zombies:SQL语句中通常允许使用换行符,它们只被视为普通的空格. (3认同)
  • 请参阅下面的答案以获取示例,您现在可以使用%. (2认同)

Rob*_*yle 164

在ruby 2.0中,您现在可以使用 %

例如:

SQL = %{
SELECT user, name
FROM users
WHERE users.id = #{var}
LIMIT #{var2}
}
Run Code Online (Sandbox Code Playgroud)

  • 使用此语法创建的字符串将包括添加到后续行的换行符和任何缩进. (23认同)
  • 也适用于Ruby 1.9.3. (14认同)
  • @Nasser Heredoc 也进行插值。 (2认同)
  • 如果使用Rails在输出上调用`squish`应该会有所帮助. (2认同)

Hon*_*gli 51

您已经阅读过多行字符串的多种语法.我最喜欢的是Perl风格:

conn.exec %q{select attr1, attr2, attr3, attr4, attr5, attr6, attr7
      from table1, table2, table3, etc, etc, etc, etc, etc,
      where etc etc etc etc etc etc etc etc etc etc etc etc etc}
Run Code Online (Sandbox Code Playgroud)

多行字符串以%q开头,后跟一个{,[或(,然后以相应的反转字符终止.%q不允许插值;%Q这样做可以这样写:

conn.exec %Q{select attr1, attr2, attr3, attr4, attr5, attr6, attr7
      from #{table_names},
      where etc etc etc etc etc etc etc etc etc etc etc etc etc}
Run Code Online (Sandbox Code Playgroud)

我实际上不知道如何调用这些类型的多行字符串,所以让我们称它们为Perl多线.

但请注意,无论您使用Perl多线还是Heredocs,Mark和Peter都建议,您最终会得到可能不必要的空格.在我的示例和它们的示例中,"from"和"where"行包含前导空格,因为它们在代码中缩进.如果不需要这个空格,那么你必须像现在一样使用连接字符串.

  • 来自#{table_names}的内容在此示例中不起作用,因为您使用%q {},如果您使用%q []或(),它将起作用 (4认同)
  • 我最喜欢的就是%{超多线字符串,带插值支持} (2认同)

Kam*_*nek 30

有时值得删除新的行字符,\n如:

conn.exec <<-eos.squish
 select attr1, attr2, attr3, attr4, attr5, attr6, attr7
 from table1, table2, table3, etc, etc, etc, etc, etc,
 where etc etc etc etc etc etc etc etc etc etc etc etc etc
eos
Run Code Online (Sandbox Code Playgroud)

  • 这是基于rails而不是ruby (4认同)

jul*_*lez 22

您也可以使用双引号

x = """
this is 
a multiline
string
"""

2.3.3 :012 > x
 => "\nthis is\na multiline\nstring\n"
Run Code Online (Sandbox Code Playgroud)

如果需要删除换行符"\n",请在每行末尾使用反斜杠"\"

  • 您可以使用单数双引号获得相同的结果.在Ruby中没有类似三重双引号的东西.它只是将它们解释为"""+"双引号,其中包含一些内容"+""`. (5认同)

Pet*_*ter 16

conn.exec = <<eos
  select attr1, attr2, attr3, attr4, attr5, attr6, attr7
  from table1, table2, table3, etc, etc, etc, etc, etc,
  where etc etc etc etc etc etc etc etc etc etc etc etc etc
eos
Run Code Online (Sandbox Code Playgroud)

  • 使用没有“-”的heredoc,如“&lt;&lt;-eos”,将包括额外的前导空格。见马克拜尔斯的回应。 (2认同)

Chr*_*bek 16

当您想要定义带有换行符和适当缩进多行字符串(自 Ruby 2.3 起可用)时,波浪形的 HEREDOC <<~就是您所需要的:

conn.exec <<~EOS
            select attr1, attr2, attr3, attr4, attr5, attr6, attr7
            from table1, table2, table3, etc, etc, etc, etc, etc
            where etc etc etc etc etc etc etc etc etc etc etc etc etc
          EOS

# -> "select...\nfrom...\nwhere..."
Run Code Online (Sandbox Code Playgroud)

如果适当的缩进不是问题,那么单引号和双引号可以在 Ruby 中跨越多行:

conn.exec "select attr1, attr2, attr3, attr4, attr5, attr6, attr7 
           from table1, table2, table3, etc, etc, etc, etc, etc, 
           where etc etc etc etc etc etc etc etc etc etc etc etc etc"    

# -> "select...\n           from...\n           where..."
      
Run Code Online (Sandbox Code Playgroud)

如果单引号或双引号因为需要大量转义而很麻烦,那么百分比字符串文字表示法 %是最灵活的解决方案:

conn.exec %(select attr1, attr2, attr3, attr4, attr5, attr6, attr7
            from table1, table2, table3, etc, etc, etc, etc, etc
            where (ProductLine = 'R' OR ProductLine = "S") AND Country = "...")
# -> "select...\n            from...\n            where..."
Run Code Online (Sandbox Code Playgroud)

如果目的是避免换行(其中两个波浪HEREDOC,报价和百分比字符串文字会引起),则续行可以通过将反斜杠使用\作为行的最后一个非空白字符。这将继续该行,并使 Ruby 将字符串背靠背连接(注意引用字符串中的那些空格):

conn.exec 'select attr1, attr2, attr3, attr4, attr5, attr6, attr7 ' \
          'from table1, table2, table3, etc, etc, etc, etc, etc, ' \
          'where etc etc etc etc etc etc etc etc etc etc etc etc etc'

# -> "select...from...where..."
Run Code Online (Sandbox Code Playgroud)

如果您使用 Rails,String.squish则将去除前导和尾随空格的字符串并将所有连续的空格(换行符、制表符和所有)折叠成一个空格:

conn.exec "select attr1, attr2, attr3, attr4, attr5, attr6, attr7 
           from table1, table2, table3, etc, etc, etc, etc, etc, 
           where etc etc etc etc etc etc etc etc etc etc etc etc etc".squish

# -> "select...attr7 from...etc, where..."
Run Code Online (Sandbox Code Playgroud)

更多细节:

Ruby HEREDOC 语法

字符串Here Document Notation是一种在代码中内联指定长文本块的方法。它<<以用户定义的字符串开头(字符串结尾终止符)。连接所有以下行,直到在行的最开头找到字符串结束符为止:

puts <<HEREDOC 
Text Text Text Text
Bla Bla
HEREDOC
# -> "Text Text Text Text\nBlaBla"
Run Code Online (Sandbox Code Playgroud)

End of String 终止符可以自由选择,但通常使用类似“EOS”(字符串结尾)或与字符串域匹配的东西,例如“SQL”。

HEREDOC默认支持插值,或者当 EOS 终止符被双引号引用时:

price = 10
print <<"EOS"  # comments can be put here
1.) The price is #{price}.
EOS
# -> "1.) The price is 10."
Run Code Online (Sandbox Code Playgroud)

如果 EOS 终止符是单引号,则可以禁用插值:

print <<'EOS' # Disabled interpolation
3.) The price is #{price}.
EOS
# -> "3.) The price is #{price}."
Run Code Online (Sandbox Code Playgroud)

的一个重要限制<<HEREDOC是 End of String 终止符需要位于行的开头:

  puts <<EOS 
    def foo
      print "foo"
    end
  EOS
EOS
#-> "....def foo\n......print "foo"\n....end\n..EOS"
Run Code Online (Sandbox Code Playgroud)

为了解决这个问题,<<-创建了语法。它允许缩进 EOS 终止符,使代码看起来更好。<<-和 EOS 终止符之间的行仍然在其完整扩展中使用,包括所有缩进:

def printExample
  puts <<-EOS # Use <<- to indent End of String terminator
    def foo
      print "foo"
    end
  EOS
end
# -> "....def foo\n......print "foo"\n....end"
Run Code Online (Sandbox Code Playgroud)

从 Ruby 2.3 开始,我们现在有了<<~删除前导空格的波浪形 HEREDOC :

puts <<~EOS # Use the squiggly HEREDOC <<~ to remove leading whitespace (since Ruby 2.3!)
  def foo
    print "foo"
  end
EOS
# -> "def foo\n..print "foo"\nend"
Run Code Online (Sandbox Code Playgroud)

<<~ 忽略空行和仅包含制表符和空格的行

puts <<~EOS.inspect 
  Hello

    World!
EOS
#-> "Hello\n..World!"
Run Code Online (Sandbox Code Playgroud)

如果同时使用制表符和空格,则制表符被视为等于 8 个空格。如果缩进最少的行位于制表符的中间,则不会删除该制表符。

puts <<~EOS.inspect
<tab>One Tab
<space><space>Two Spaces
EOS
# -> "\tOne Tab\nTwoSpaces"
Run Code Online (Sandbox Code Playgroud)

HEREDOC 可以做一些疯狂的事情,例如使用反引号执行命令:

puts <<`EOC`            
echo #{price}
echo #{price * 2}
EOC
Run Code Online (Sandbox Code Playgroud)

HEREDOC 字符串定义可以“堆叠”,这意味着第一个 EOS 终止符(下面的 EOSFOO)将结束第一个字符串并开始第二个(下面的 EOSBAR):

print <<EOSFOO, <<EOSBAR    # you can stack them
I said foo.
EOSFOO
I said bar.
EOSBAR
Run Code Online (Sandbox Code Playgroud)

我认为没有人会像这样使用它,但<<EOS它实际上只是一个字符串文字,可以放在通常可以放置字符串的任何地方:

def func(a,b,c)
  puts a
  puts b
  puts c
end

func(<<THIS, 23, <<THAT) 
Here's a line
or two.
THIS
and here's another.
THAT
Run Code Online (Sandbox Code Playgroud)

如果您没有 Ruby 2.3,但是有 Rails >=3.0,那么您可以使用String.strip_heredocwhich<<~

# File activesupport/lib/active_support/core_ext/string/strip.rb, line 22
class String
  def strip_heredoc
    gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, "".freeze)
  end
end

puts <<-USAGE.strip_heredoc # If no Ruby 2.3, but Rails >= 3.0
  This command does such and such.

  Supported options are:
    -h         This message
    ...
USAGE
Run Code Online (Sandbox Code Playgroud)

故障排除

如果您在 Ruby 解析您的文件时看到错误,那么很可能是您有额外的前导或尾随空格带有 HEREDOC 或带有波浪形 HEREDOC 的额外尾随空格。例如:

你看到什么了:

    database_yml = <<~EOS
      production:
        database: #{fetch(:user)}
        adapter: postgresql
        pool: 5
        timeout: 5000
    EOS  
Run Code Online (Sandbox Code Playgroud)

Ruby 告诉你的:

SyntaxError: .../sample.rb:xx: can't find string "EOS" anywhere before EOF
...sample.rb:xx: syntax error, unexpected end-of-input, expecting `end'
Run Code Online (Sandbox Code Playgroud)

有什么过错:

在终止 EOS 后找出多余的空格

在终止 EOS 后找出多余的空格。

百分比字符串文字

RubyDoc如何使用百分号然后在括号中的字符串进行配对,诸如%(...)%[...]%{...}等,或一对任何非字母数字字符的诸如%+...+

最后的话

最后,得到原始问题“有没有办法暗示串联?”的答案。回答:如果背靠背找到两个字符串(单引号和双引号),Ruby 总是暗示连接:

puts "select..." 'from table...' "where..."
# -> "select...from table...where..."
Run Code Online (Sandbox Code Playgroud)

需要注意的是,这在换行符之间不起作用,因为 Ruby 正在解释语句的结尾,而一行中仅字符串的后续行不会做任何事情。


Ale*_*hen 14

其他选择:

#multi line string
multiline_string = <<EOM
This is a very long string
that contains interpolation
like #{4 + 5} \n\n
EOM

puts multiline_string

#another option for multiline string
message = <<-EOF
asdfasdfsador #{2+2} this month.
asdfadsfasdfadsfad.
EOF

puts message
Run Code Online (Sandbox Code Playgroud)


Msh*_*hka 11

最近有了Ruby 2.3中的新功能,新版本squiggly HEREDOC将让你以一种很好的方式编写我们的多行字符串并进行最小的更改,因此结合使用它.squish可以让你以一种很好的方式编写多行!

[1] pry(main)> <<~SQL.squish
[1] pry(main)*   select attr1, attr2, attr3, attr4, attr5, attr6, attr7
[1] pry(main)*   from table1, table2, table3, etc, etc, etc, etc, etc,
[1] pry(main)*   where etc etc etc etc etc etc etc etc etc etc etc etc etc
[1] pry(main)* SQL
=> "select attr1, attr2, attr3, attr4, attr5, attr6, attr7 from table1, table2, table3, etc, etc, etc, etc, etc, where etc etc etc etc etc etc etc etc etc etc etc etc etc"
Run Code Online (Sandbox Code Playgroud)

参考:https://infinum.co/the-capsized-eight/multiline-strings-ruby-2-3-0-the-squiggly-heredoc


Pwn*_*rar 8

为了避免关闭每一行的括号,您可以简单地使用带反斜杠的双引号来转义换行符:

"select attr1, attr2, attr3, attr4, attr5, attr6, attr7 \
from table1, table2, table3, etc, etc, etc, etc, etc, \
where etc etc etc etc etc etc etc etc etc etc etc etc etc"
Run Code Online (Sandbox Code Playgroud)


小智 7

conn.exec 'select attr1, attr2, attr3, attr4, attr5, attr6, attr7 ' <<
        'from table1, table2, table3, etc, etc, etc, etc, etc, ' <<
        'where etc etc etc etc etc etc etc etc etc etc etc etc etc'
Run Code Online (Sandbox Code Playgroud)

<<是字符串的连接运算符

  • `+` 是常规连接运算符,`&lt;&lt;` 是 *in-place* 附加运算符。在文字上使用副作用碰巧在这里起作用(第一个字符串被修改了两次并返回),但恕我直言,这很奇怪,让我做了一个双重拍摄,其中`+` 将非常清楚。但也许我只是 Ruby 的新手...... (3认同)

San*_*ane 6

今天优雅的回答:

<<~TEXT
Hi #{user.name}, 

Thanks for raising the flag, we're always happy to help you.
Your issue will be resolved within 2 hours.
Please be patient!

Thanks again,
Team #{user.organization.name}
TEXT
Run Code Online (Sandbox Code Playgroud)

<<-TEXT和是有区别的<<~TEXT,前者保留块内的间距,后者则不保留。

还有其他选择。就像串联等一样,但这通常更有意义。

如果我在这里错了,请告诉我如何......


Aid*_*lly 5

conn.exec [
  "select attr1, attr2, attr3, ...",
  "from table1, table2, table3, ...",
  "where ..."
].join(' ')
Run Code Online (Sandbox Code Playgroud)

这个建议比 here-documents 和长字符串有优势,自动缩进可以适当地缩进字符串的每个部分。但它是以效率为代价的。


Unc*_*ene 5

如果你的头脑多余的空格和换行,你可以使用

conn.exec %w{select attr1, attr2, attr3, attr4, attr5, attr6, attr7
  from table1, table2, table3, etc, etc, etc, etc, etc,
  where etc etc etc etc etc etc etc etc etc etc etc etc etc} * ' '
Run Code Online (Sandbox Code Playgroud)

(使用%W作为插值字符串)