簡體   English   中英

Ruby:我可以編寫沒有連接的多行字符串嗎?

[英]Ruby: Can I write multi-line string with no concatenation?

有沒有辦法讓它看起來更好一點?

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"

作為獎勵,這是一個使用有趣的 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"

后者主要用於在處理中需要更多靈活性的情況。 我個人不喜歡它,它把處理放在一個奇怪的地方 wrt 字符串(即,在它前面,但使用通常在后面的實例方法),但它就在那里。 請注意,如果您要縮進最后一個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"

在 ruby​​ 2.0 中,您現在可以使用%

例如:

    SQL = %{
      SELECT user, name
      FROM users
      WHERE users.id = #{var}
      LIMIT #{var2}
    }

是的,如果您不介意插入額外的換行符:

 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

正如您已經閱讀過的,多行字符串有多種語法。 我最喜歡的是 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 多行還是按照 Mark 和 Peter 的建議使用heredoc,最終都會出現潛在的不必要的空格。 在我的示例及其示例中,“from”和“where”行都包含前導空格,因為它們在代碼中縮進。 如果不需要這個空格,那么您必須像現在一樣使用連接的字符串。

有時值得刪除換行符\\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”,請在每行末尾使用反斜杠“\\”

其他選項:

#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
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

最近隨着 Ruby 2.3 中的新特性,新的squiggly HEREDOC將讓您以最少的更改以漂亮的方式編寫我們的多行字符串,因此將其與.squish結合使用(如果您使用的是 Rails)將使您以漂亮的方式編寫多行大大地! 如果只使用 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

當您想要定義帶有換行符和適當縮進多行字符串(自 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..."

如果適當的縮進不是問題,那么單引號和雙引號可以在 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..."
      

如果單引號或雙引號因為需要大量轉義而很麻煩,那么百分比字符串文字符號%是最靈活的解決方案:

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..."

如果目的是避免換行(其中兩個波浪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..."

如果您使用 Rails,那么String.squishString.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..."

更多細節:

Ruby HEREDOC 語法

字符串Here Document Notation是一種在代碼中內聯指定長文本塊的方法。 它以<<開頭,后跟一個用戶定義的字符串(字符串結束符)。 連接所有以下行,直到在行的最開頭找到字符串結束符為止:

puts <<HEREDOC 
Text Text Text Text
Bla Bla
HEREDOC
# -> "Text Text Text Text\nBlaBla"

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."

如果 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 或帶有波浪形 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 后找出多余的空格

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

百分比字符串文字

RubyDoc如何使用百分號然后在一對括號的字符串,如%(...) %[...] %{...}等,或一對任何非的字母數字字符,例如%+...+

最后的話

最后,得到原始問題“有沒有辦法暗示串聯?”的答案。 回答:如果背靠背找到兩個字符串(單引號和雙引號),Ruby 總是暗示連接:

puts "select..." 'from table...' "where..."
# -> "select...from table...where..."

需要注意的是,這在換行符之間不起作用,因為 Ruby 正在解釋語句的結尾,而一行中僅字符串的后續行不會做任何事情。

為了避免關閉每一行的括號,您可以簡單地使用帶反斜杠的雙引號來轉義換行符:

"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 %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} * ' '

(使用 %W 插入字符串)

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, ...",
  "from table1, table2, table3, ...",
  "where ..."
].join(' ')

這個建議比 here-documents 和長字符串有優勢,自動縮進可以適當地縮進字符串的每個部分。 但它是以效率為代價的。

今天優雅的回答:

<<~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

<<-TEXT<<~TEXT有區別,前者保留塊內的間距,后者不保留。

還有其他選擇。 像串聯等,但一般來說這個更有意義。

如果我在這里錯了,請告訴我如何...

和你一樣,我也在尋找一個不包含換行符的解決方案。 (雖然它們在 SQL 中可能是安全的,但在我的情況下它們並不安全,而且我有一大塊文本需要處理)

這可以說同樣丑陋,但您可以在heredoc中反斜杠轉義換行符以從結果字符串中省略它們:

conn.exec <<~END_OF_INPUT
    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
  END_OF_INPUT

請注意,您不能在沒有插值(IE <<~'END_OF_INPUT' )的情況下完成此操作,所以要小心。 #{expressions}將在此處進行評估,而不會在您的原始代碼中進行評估。 A.出於這個原因, Wilson 的答案可能更好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM