Was ist los mit Groovy Multi-Line String?

105

Groovy-Skripte lösen einen Fehler aus:

def a = "test"
  + "test"
  + "test"

Error:

No signature of method: java.lang.String.positive() is 
applicable for argument types: () values: []

Während dieses Skript gut funktioniert:

def a = new String(
  "test"
  + "test"
  + "test"
)

Warum?

yegor256
quelle
5
Falls es jemand anderem hilft, können Sie den gleichen Fehler mit Code wie erhalten def a = b + + "/" + c. In diesem Fall sind die beiden + Symbole offensichtlich das Problem.
Geoff Hackworth

Antworten:

236

Da groovy keinen EOL-Marker (wie z. B. ;) hat, wird es verwirrt, wenn Sie den Operator in die folgende Zeile setzen

Dies würde stattdessen funktionieren:

def a = "test" +
  "test" +
  "test"

wie der Groovy-Parser in der folgenden Zeile zu erwarten weiß

Groovy sieht Ihr Original defals drei separate Aussagen. Der erste weist testzu a, die zweiten beiden versuchen, "test"positiv zu machen (und hier schlägt es fehl)

Bei der new StringKonstruktormethode befindet sich der Groovy-Parser noch im Konstruktor (da die Klammer noch nicht geschlossen wurde), sodass die drei Zeilen logisch zu einer einzigen Anweisung zusammengefügt werden können

Für echte mehrzeilige Zeichenfolgen können Sie auch das dreifache Anführungszeichen verwenden:

def a = """test
test
test"""

Erstellt einen String mit Test in drei Zeilen

Sie können es auch ordentlicher machen, indem Sie:

def a = """test
          |test
          |test""".stripMargin()

Die stripMarginMethode schneidet die linke |Zeile (bis einschließlich des Zeichens) von jeder Zeile ab

tim_yates
quelle
6
Oder verwenden Sie einfach stripIndent () anstelle von stripMargin().
Sschuberth
Ja, und lassen Sie die |Zeichen in den zusätzlichen Zeilen
weg
4
Sie können doppelte Anführungszeichen in """Zeichenfolgen verwenden
tim_yates
3
Richtig, ich habe die Antwort bearbeitet, um zu zeigen, wie Sie den Code leicht neu formatieren müssen, damit er stripIndent()funktioniert.
Sschuberth
2
Weil a) ich es bereits als Kommentar gepostet habe und b) es sich nicht wesentlich von dieser Antwort unterscheidet.
Sschuberth
17

Sie können Groovy mitteilen, dass die Anweisung über das Zeilenende hinaus ausgewertet werden soll, indem Sie ein Paar Klammern hinzufügen ( ... )

def a = ("test"
  + "test"
  + "test")

Eine zweite Möglichkeit besteht darin \, am Ende jeder Zeile einen Backslash zu verwenden :

def a = "test" \
  + "test" \
  + "test"

FWIW, dies ist identisch mit der Funktionsweise von mehrzeiligen Python-Anweisungen.

cmcginty
quelle
Die zweite ist auch, wie VBA mehrzeilige Anweisungen funktionieren: D (Nur mit Unterstrichen anstelle von Backslashes, weil VBA.)
Charles Wood
Die zweite Option ist in einer Jenkins-Datei für mich fehlgeschlagen. Erste Option hat funktioniert.
SilverJan
Nitpick: Für mehrzeilige Python-Zeichenfolgen ist bei Verwendung von Parens kein Verkettungsoperator erforderlich, daher ist dies nicht genau dasselbe.
Big McLargeHuge
17

Ähnlich wie stripMargin()könnten Sie auch stripIndent () like verwenden

def a = """\
        test
        test
        test""".stripIndent()

Wegen

Die Zeile mit der geringsten Anzahl führender Leerzeichen bestimmt die zu entfernende Anzahl.

Sie müssen auch den ersten "Test" einrücken und nicht direkt nach dem Anfang einfügen """(dies \stellt sicher, dass die mehrzeilige Zeichenfolge nicht mit einer neuen Zeile beginnt).

sschuberth
quelle
2
Wofür ist das?
Joe Phillips
4
Ich habe meinen letzten Satz verbessert, um ihn besser zu erklären.
Sschuberth