有没有办法让这个看起来更好一些?
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'
比如说,有没有一种方式可以暗示字符串拼接?
有没有办法让这个看起来更好一些?
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'
比如说,有没有一种方式可以暗示字符串拼接?
这个答案的一些部分帮助我得到了所需的东西(易于多行连接而没有额外的空格),但由于实际答案中没有,所以我在这里整理它们:
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"
p <<END_SQL.gsub(/\s+/, " ").strip
SELECT * FROM users
ORDER BY users.id DESC
END_SQL
# >> "SELECT * FROM users ORDER BY users.id DESC"
END_SQL
标识符(这很常见,因为这可能是在函数或模块内部),则需要使用连字符语法(即p <<-END_SQL
而不是p <<END_SQL
)。否则,缩进的空格会导致标识符被解释为字符串的连续部分。
这并没有节省太多打字时间,但我觉得它比使用加号看起来更好。
另外(我在编辑中说,几年后),如果您使用的是Ruby 2.3+,运算符<<~ 也可用,它会从最终字符串中删除额外的缩进。在这种情况下,您应该能够删除.gsub
调用(尽管它可能取决于起始缩进和您的最终需求)。
编辑:再添加一个:
p %{
SELECT * FROM users
ORDER BY users.id DESC
}.gsub(/\s+/, " ").strip
# >> "SELECT * FROM users ORDER BY users.id DESC"
%
。 SQL = %{
SELECT user, name
FROM users
WHERE users.id = #{var}
LIMIT #{var2}
}
squish
应该会很有帮助。 - Jignesh Gohel如果您不介意插入额外的换行符,那么是可以的:
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'
或者你可以使用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
%Q(...)
。 - BaroqueBobcat%(...)
。 - zero-divisor<<~
是您要寻找的内容(自Ruby 2.3以来可用)。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..."
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..."
%
是最灵活的解决方案: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..."
\
放在行的末尾非空格字符处。这将继续该行,并使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..."
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..."
更多细节:
字符串的 Here Document 符号是一种在代码中内联指定长文本块的方法。它以<<
开头,后跟用户定义的字符串(字符串结束符)。所有以下行都会被连接起来,直到找到字符串结束符位于行的最开始位置为止:
puts <<HEREDOC
Text Text Text Text
Bla Bla
HEREDOC
# -> "Text Text Text Text\nBlaBla"
字符串的结束符可以自由选择,但通常使用类似于“EOS”(字符串结束)或与字符串域匹配的内容,例如“SQL”。
HEREDOC默认支持插值,或者当EOS终止符被双引号引用时:
price = 10
print <<"EOS" # comments can be put here
1.) The price is #{price}.
EOS
# -> "1.) The price is 10."
如果EOS终止符使用单引号,则可以禁用插值:
print <<'EOS' # Disabled interpolation
3.) The price is #{price}.
EOS
# -> "3.) The price is #{price}."
<<HEREDOC
的一个重要限制是字符串终止符需要在行首:
puts <<EOS
def foo
print "foo"
end
EOS
EOS
#-> "....def foo\n......print "foo"\n....end\n..EOS"
<<-
语法。它允许将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"
自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"
空行和只包含制表符和空格的行将被 <<~ 忽略。
puts <<~EOS.inspect
Hello
World!
EOS
#-> "Hello\n..World!"
如果同时使用制表符和空格,则制表符被视为等于8个空格。 如果最小缩进的行位于一个制表符的中间,则该制表符不会被移除。
puts <<~EOS.inspect
<tab>One Tab
<space><space>Two Spaces
EOS
# -> "\tOne Tab\nTwoSpaces"
HEREDOC可以做一些疯狂的事情,比如使用反引号执行命令:
puts <<`EOC`
echo #{price}
echo #{price * 2}
EOC
HEREDOC字符串定义可以“堆叠”,这意味着第一个EOS终止符(下面的EOSFOO)将结束第一个字符串并开始第二个字符串(下面的EOSBAR):
print <<EOSFOO, <<EOSBAR # you can stack them
I said foo.
EOSFOO
I said bar.
EOSBAR
我认为没有人会像这样使用它,但是<<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
如果你没有 Ruby 2.3,但是有 Rails >=
3.0,那么你可以使用 String.strip_heredoc
,它与 <<~
的作用相同。
# 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
如果在Ruby解析文件时出现错误,那么最有可能的原因是您在HEREDOC中有额外的前导或尾随空格,或者在squiggly HEREDOC中有额外的尾随空格。例如:
您看到的:
database_yml = <<~EOS
production:
database: #{fetch(:user)}
adapter: postgresql
pool: 5
timeout: 5000
EOS
Ruby 告诉你的:
SyntaxError: .../sample.rb:xx: can't find string "EOS" anywhere before EOF
...sample.rb:xx: syntax error, unexpected end-of-input, expecting `end'
问题出在哪里:
找出终止EOS后的额外空格。
有关如何使用带括号对的百分号后跟字符串(例如%(...)
,%[...]
,%{...}
等)或任何非字母数字字符对的一些信息,请参见RubyDoc。
最后,回答原始问题“是否有一种方法暗示连接?”:如果发现两个字符串(单引号和双引号)背靠背,则Ruby总是暗示连接:
puts "select..." 'from table...' "where..."
# -> "select...from table...where..."
需要注意的是,这种方法不能跨越换行符使用,因为Ruby会解释语句结束,并且仅由字符串组成的连续行不会执行任何操作。
%{}
、%()
和%[]
字符串的处理方式没有任何区别。你只需选择在字符串内部最不可能使用的终止符,从而减少(或几乎消除)需要进行转义的必要性。例如,在SPARQL查询中,{}
和()
是常见的,[]
可以用于列表,因此使用%$$
是有意义的。在SQL中,[]
和()
也很常见,%{}
可能是一个不错的选择(也许除了T-SQL)。我还喜欢选择在Bash中需要转义的字符,\$
看起来很自然。 - berezovskyi有多种多行字符串的语法,就像你已经阅读过的一样。我最喜欢的是 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}
多行字符串以%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}
实际上我不知道这种多行字符串被称为什么,所以我们就叫它Perl多行。
请注意,无论您是使用像马克和彼得建议的Perl多行还是heredocs,都可能会产生不必要的空格。在我的示例和他们的示例中,“from”和“where”行包含前导空格,因为它们在代码中的缩进。如果不需要这个空格,则必须像您现在正在做的那样使用连接字符串。
%q
系列的字符串将包含换行符,这与原始代码不等同。 - Josh有时候删除换行符\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
你也可以使用双引号
x = """
this is
a multiline
string
"""
2.3.3 :012 > x
=> "\nthis is\na multiline\nstring\n"
如果需要去除换行符"\n",请在每行结尾处使用反斜杠"\"
"" + "带有一些内容的双引号" + ""
。 - rakvium ""+"\nhello\n""
确实看起来很奇怪。 - juliangonzalez"x"
比"""x"""
(基本上与""+"x"+""
)或"""""x"""""
(与"" + "" + "x" + "" + ""
相同)更好看,更快。这是Ruby,不是Python,在需要多行字符串时使用"""
而不是"
。 - rakvium其他选项:
#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
<<EOM
改为 <<-EOM
,对吧? - kingPuppy<<-EOF
示例似乎可以工作。我猜任何一种方式都可以。 - Alex Cohen最近,随着Ruby 2.3的新功能,新的squiggly HEREDOC
可以让您以一种美观简洁的方式编写多行字符串,而只需进行最小程度的更改。如果您正在使用Rails,则可以将其与.squish
结合使用,以便以美观的方式编写多行字符串!
如果仅使用Ruby,则可以执行<<~SQL.split.join(" ")
,这几乎是相同的。
[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"
参考: https://infinum.co/the-capsized-eight/multiline-strings-ruby-2-3-0-the-squiggly-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
p <<END_SQL
应该是p <<-END_SQL
。否则这就是答案。你可以使用波浪线 HEREDOC 运算符<<~END_SQL
来去掉前导空格(可选)。 - user483040.gsub
和.strip
会改变它们的目标对象,而冻结字符串是不可变的;这可能意味着您正在Rails 2.3+项目中使用frozen_string_literal
编译指示(并对字面字符串执行此操作)。使用其他答案之一依赖于连接而不是突变应该适用于您(删除额外的空格仍需要解冻字符串)。 - A. Wilson