488 Stimmen

Rubin: Kann ich einen mehrzeiligen String ohne Verkettung schreiben?

Gibt es eine Möglichkeit, dies ein wenig besser aussehen zu lassen?

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'

Gibt es zum Beispiel eine Möglichkeit, eine Verkettung zu implizieren?

685voto

A. Wilson Punkte 8084

Es gibt Teile dieser Antwort, die mir geholfen haben, das zu bekommen, was ich brauchte (einfache mehrzeilige Verkettung OHNE zusätzliche Leerzeichen), aber da keine der aktuellen Antworten dies enthielt, stelle ich sie hier zusammen:

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"

Als Bonus gibt es hier eine Version mit der lustigen HEREDOC-Syntax (via dieser Link ):

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

Letzteres wäre vor allem für Situationen gedacht, die mehr Flexibilität bei der Verarbeitung erfordern. Ich persönlich mag es nicht, da es die Verarbeitung an eine seltsame Stelle in Bezug auf die Zeichenkette bringt (d.h., vor der Zeichenkette, aber mit Instanzmethoden, die normalerweise danach kommen), aber es ist da. Beachten Sie, dass, wenn Sie die letzte Zeile einrücken END_SQL Bezeichner (was üblich ist, da dieser wahrscheinlich innerhalb einer Funktion oder eines Moduls steht), müssen Sie die Syntax mit Bindestrich verwenden (d. h., p <<-END_SQL anstelle von p <<END_SQL ). Andernfalls wird der Bezeichner aufgrund des eingerückten Leerzeichens als Fortsetzung der Zeichenkette interpretiert.

Das spart zwar nicht viel Tipparbeit, sieht aber besser aus als die Verwendung von +-Zeichen, wie ich finde.

Außerdem (ich sage es in einem Edit, mehrere Jahre später), wenn Sie Ruby 2.3+ benutzen, ist der Operator <<~ ist auch verfügbar , wodurch zusätzliche Einrückungen in der endgültigen Zeichenkette entfernt werden. Sie sollten in der Lage sein, die .gsub Aufruf, in diesem Fall (obwohl es sowohl von der Anfangseinrückung als auch von Ihren endgültigen Bedürfnissen abhängen könnte).

EDIT: Ich füge einen weiteren hinzu:

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

220voto

Robbie Guilfoyle Punkte 3187

In Ruby 2.0 können Sie jetzt einfach %

Zum Beispiel:

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

176voto

Mark Byers Punkte 761508

Ja, wenn Sie nichts gegen die zusätzlichen Zeilenumbrüche haben:

 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'

Alternativ können Sie auch eine 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

52voto

Christopher Oezbek Punkte 20239

Diese Frage hat mich dazu gebracht, die Funktionsweise von HEREDOC zu verstehen. Verzeihen Sie mir, wenn die Antwort zu lang geworden ist.

El verschnörkelter HEREDOC <<~ ist das, wonach Sie suchen, wenn Sie eine mehrzeilige Zeichenfolge mit Zeilenumbrüchen und korrekter Einrückung (verfügbar seit 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..."

Wenn eine ordnungsgemäße Einrückung nicht von Bedeutung ist, dann einfache und doppelte Anführungszeichen kann sich in Ruby über mehrere Zeilen erstrecken:

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

Wenn einfache oder doppelte Anführungszeichen umständlich sind, weil sie eine Menge Escaping erfordern würden, dann ist die prozentuale String-Literal-Schreibweise % ist die flexibelste Lösung:

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

Wenn das Ziel ist, die Zeilenumbrüche zu vermeiden (die sowohl der verschnörkelte HEREDOC, die Anführungszeichen als auch das prozentuale Zeichenfolgenliteral verursachen), dann ist ein Zeilenfortsetzung kann durch einen Backslash verwendet werden \ als letztes Zeichen ohne Leerzeichen in einer Zeile. Dies setzt die Zeile fort und veranlasst Ruby, die Strings Rücken an Rücken zu verketten (achten Sie auf die Leerzeichen innerhalb des zitierten Strings):

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

Wenn Sie Rails verwenden, dann String.squish entfernt in der Zeichenkette führende und nachfolgende Leerzeichen und fasst alle aufeinander folgenden Leerzeichen (Zeilenumbrüche, Tabulatoren und alle) zu einem einzigen Leerzeichen zusammen:

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

Weitere Einzelheiten:

Ruby HEREDOC-Syntax

El Hier Dokumentennotation für Zeichenketten ist eine Möglichkeit, lange Textblöcke inline im Code zu kennzeichnen. Er wird gestartet durch << gefolgt von einer benutzerdefinierten Zeichenkette (dem End of String Terminator). Alle folgenden Zeilen werden aneinandergereiht, bis der End of String-Terminator an der allererster Schritt einer Linie:

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

Das Ende der Zeichenkette kann frei gewählt werden, aber es ist üblich, etwas wie "EOS" (Ende der Zeichenkette) oder etwas, das dem Bereich der Zeichenkette entspricht, wie "SQL", zu verwenden.

HEREDOC unterstützt Interpolation standardmäßig oder wenn der EOS-Terminator in Anführungszeichen steht:

price = 10
print <<"EOS"  # comments can be put here
1.) The price is #{price}.
EOS
# -> "1.) The price is 10."

Die Interpolation kann deaktiviert werden, wenn der EOS-Terminator in einfachen Anführungszeichen steht:

print <<'EOS' # Disabled interpolation
3.) The price is #{price}.
EOS
# -> "3.) The price is #{price}."

Eine wichtige Einschränkung der <<HEREDOC ist, dass das Ende der Zeichenkette am Anfang der Zeile stehen muss:

  puts <<EOS 
    def foo
      print "foo"
    end
  EOS
EOS
#-> "....def foo\n......print "foo"\n....end\n..EOS"

Um dies zu umgehen, wird die <<- Syntax erstellt wurde. Sie erlaubt es, den EOS-Terminator einzurücken, um den Code schöner aussehen zu lassen. Die Zeilen zwischen den <<- und EOS-Terminator werden weiterhin in vollem Umfang einschließlich aller Einrückungen verwendet:

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"

Seit Ruby 2.3 haben wir nun das verschnörkelte HEREDOC <<~ wodurch führende Leerzeichen entfernt werden:

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"

Leere Zeilen und Zeilen, die nur Tabulatoren und Leerzeichen enthalten, werden von <<~ ignoriert.

puts <<~EOS.inspect 
  Hello

    World!
EOS
#-> "Hello\n..World!"

Werden sowohl Tabulatoren als auch Leerzeichen verwendet, gelten Tabulatoren als gleichwertig mit 8 Leerzeichen. Befindet sich die Zeile mit der geringsten Einrückung in der Mitte eines Tabulators, wird dieser nicht entfernt.

puts <<~EOS.inspect
<tab>One Tab
<space><space>Two Spaces
EOS
# -> "\tOne Tab\nTwoSpaces"

HEREDOC kann einige verrückte Dinge tun, zum Beispiel Befehle mit Backticks ausführen:

puts <<`EOC`            
echo #{price}
echo #{price * 2}
EOC

HEREDOC-String-Definitionen können "gestapelt" werden, was bedeutet, dass der erste EOS-Terminator (EOSFOO unten) den ersten String beendet und den zweiten beginnt (EOSBAR unten):

print <<EOSFOO, <<EOSBAR    # you can stack them
I said foo.
EOSFOO
I said bar.
EOSBAR

Ich glaube nicht, dass jemand es jemals als solches benutzen würde, aber die <<EOS ist eigentlich nur ein String-Literal und kann überall dort eingefügt werden, wo normalerweise ein String eingefügt werden kann:

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

Wenn Sie nicht Ruby 2.3 haben, sondern Rails >= 3.0 dann können Sie String.strip_heredoc was dasselbe bewirkt wie <<~

# 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

Fehlersuche

Wenn Sie Fehler sehen, wenn Ruby Ihre Datei parst, dann ist es sehr wahrscheinlich, dass Sie entweder zusätzliche führende oder nachgestellte Leerzeichen mit einem HEREDOC oder zusätzliche nachgestellte Leerzeichen mit einem verschnörkelten HEREDOC haben. Zum Beispiel:

Was Sie sehen:

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

Was Ruby Ihnen erzählt:

SyntaxError: .../sample.rb:xx: can't find string "EOS" anywhere before EOF
...sample.rb:xx: syntax error, unexpected end-of-input, expecting `end'

Was ist der Fehler?

Spot the extra spaces after the terminating EOS

Beachten Sie die zusätzlichen Leerzeichen nach dem abschließenden EOS.

Prozentuale String-Literale

Ver RubyDoc für die Verwendung des Prozentzeichens gefolgt von einer Zeichenkette in einem Klammerpaar wie z. B. einer %(...) , %[...] , %{...} , usw. oder ein Paar beliebiger nicht-alphanumerischer Zeichen wie %+...+

Letzte Worte

Zuletzt, um die Antwort auf die ursprüngliche Frage "Gibt es eine Möglichkeit, die Verkettung zu implizieren?" beantwortet: Ruby impliziert immer eine Verkettung, wenn zwei Zeichenketten (einfach und doppelt zitiert) hintereinander gefunden werden:

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

Die Einschränkung ist, dass dies nicht über Zeilenumbrüche hinweg funktioniert, da Ruby ein Ende der Anweisung interpretiert und die Folgezeile von Strings allein in einer Zeile nichts bewirkt.

49voto

Hongli Punkte 18294

Wie Sie bereits gelesen haben, gibt es mehrere Syntaxen für mehrzeilige Zeichenketten. Mein Favorit ist der Perl-Stil:

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}

Die mehrzeilige Zeichenkette beginnt mit %q, gefolgt von einem {, [ oder (, und endet mit dem entsprechenden umgekehrten Zeichen. %q erlaubt keine Interpolation; %Q hingegen schon, so dass Sie Dinge wie diese schreiben können:

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}

Ich habe eigentlich keine Ahnung, wie diese Art von mehrzeiligen Zeichenketten genannt werden, also nennen wir sie einfach Perl-Multilines.

Beachten Sie jedoch, dass Sie, egal ob Sie Perl-Mehrzeilen oder Heredocs verwenden, wie Mark und Peter vorgeschlagen haben, potenziell unnötige Leerzeichen haben. Sowohl in meinen als auch in ihren Beispielen enthalten die "from"- und "where"-Zeilen aufgrund ihrer Einrückung im Code führende Leerzeichen. Wenn diese Leerzeichen nicht erwünscht sind, müssen Sie verkettete Zeichenketten verwenden, wie Sie es jetzt tun.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X