Groovy: Verständnis eines regulären Ausdrucks

Studdi23

Mitglied
Hallo zusammen,

ich lerne zur Zeit groovy und gehe gerade ein Tutorial durch. Momentan arbeite ich mich durch reguläre Ausdrucke und versuche folgenden Ausdruck zu verstehen:
Java:
// Every word must be followed by a nonword character
def text = "John Jimbo jingeled happily ever after"
    
 if (text=~/(\w*\W+)*/){
      println "Find was successful"
    } else {
      println "Find was not successful"
}

Beim Ausführen des Skripts wird immer "Find was successful" ausgegeben. Mir ist aber nicht ganz klar warum das so ist. Wenn ich das richtig verstanden habe sucht der Ausdruck nach allen Wörtern (bestehend aus [a-zA-Z_0-9]), die mit einem Sonderzeichnen enden, was ja auf den Text "John Jimbo jingeled happily ever after" nicht zutrifft, oder doch?!? Nun habe ich mal alle Vorkomnisse testweise mit einem "x" ersetzt
Java:
def repl = (text =~ /(\w*\W+)*/).replaceAll("x")
println repl
und erhalte daraufhin folgende Ausgabe xxaxfxtxexrx, die mich dann vollends verwirrt hat. Könnte mir das bitte vielleicht jemand erklären, stehe total auf dem Schlauch.

Gruß
Studdi23
 

turtle

Top Contributor
Ich kenne mich mit Groovy nicht aus, kann aber was zum regulären Ausdruck sagen

Text: "John Jimbo jingeled happily ever after"
RegExp: ~(\w*\W+)*
Code:
~
das Zeichen ~ Wenn du Start der Zeile meinst, das ist ^
Code:
(
Hier beginnt eine Capturing group, die alles bis zur schliessenden Klammer umfasst
Code:
\w
ist ein Word-Character, also [a-zA-Z_0-9] wie du schon geschrieben hast
also word-Character 0 bis n-mal, also erkennt es John
Code:
\W
alles was nicht Word-Character ist, also beispielsweise Leerzeichen
Code:
+
1-mal oder mehrmals also sind wir bei "John "
Code:
)
Capturing group Ende
Code:
*
Diese Group darf es also 0 bis n-mal geben, also sind wir bei "John Jimbo jingeled happily ever after"
sprich der gesamte Text wird gematched

Das Replace ersetzt die Capturing-Group durch den Ersatz-Text,also alles durch x, ergibt bei mir John Jimbo jingeled happily ever after --> x
 

Tobse

Top Contributor
Code:
*
Diese Group darf es also 0 bis n-mal geben, also sind wir bei "John Jimbo jingeled happily ever after"
sprich der gesamte Text wird gematched

Da muss ich dir wiedersprechen. Das "after" wird nciht gematcht weil kein non-word character dahionter steht. Damit das "after" auch gematcht wird müsste entweder der String "John Jimbo jingeled happily ever after " sein oder aber die Regex das letzt Wort speziell behandeln:
Code:
^((\w*\W+)*(\w*)?)$
 

turtle

Top Contributor
Du hast natürlich Recht, aber...

Ich habe mit dem RegExp-Plugin in Eclipse nachgeschaut und verifiziert, das der ganze Text matched.

\w ist [^a-zA-Z_0-9] und somit wird auch "after" gematched weil danach weder a-zA-Z etc. da steht, sondern nix mehr, sondern praktisch $ (end-of-line).

Ob in Groovy eine andere regular Expression engine am Werke ist, die das anders handhabt, MAG sein, glaube ich aber nicht wirklich;)

Mehr wunderte mich, das der TO sagte, groovy würde einen Match liefern, obwohl der Text NICHT mit einer Tilde begann.
 

Studdi23

Mitglied
Hallo Leute,

danke erstmal für eure Antworten.

@turtle
Mehr wunderte mich, das der TO sagte, groovy würde einen Match liefern, obwohl der Text NICHT mit einer Tilde begann.
Die Tilde gehört zum Gleichheitszeichen und bedeutet, dass Groovy Teil-Matches innerhalb des Textes finden soll. Soll der ganze String gematched werden wird das in Groovy mit einem ==~ ausgedrückt.

\w ist [^a-zA-Z_0-9] und somit wird auch "after" gematched weil danach weder a-zA-Z etc. da steht, sondern nix mehr, sondern praktisch $ (end-of-line).
Da war ich mir auch nicht ganz sicher, ob ein "non-printable character" wie EOF ebenfalls als "non-word character" zählt. Jedenfalls hätte ich, so wie auch du und Tobse, erwartet, daß jedes durch Leerzeichen getrennte Wort durch das "replaceAll" mit einem "x" ersetzt werden würde. Die Ausgabe hätte dann, je nachdem ob das "after" am Ende gematched wird oder nicht, entweder xxxxxx oder xxxxxafter lauten müssen. Aber die Ausgabe xxaxfxtxexrx lässt mich ehrlich gesagt zweifeln, ob die Regex-Engine, wie von dir ebenfalls bereits vermutet, Ausdrücke eventuell doch anders interpretiert. Glaube ich persönlich aber auch nicht. Vielleicht könnte ein Groovy Experte hier noch mal Licht ins dunkel bringen.
 
Zuletzt bearbeitet:

turtle

Top Contributor
Die Tilde gehört zum Gleichheitszeichen und bedeutet, dass Groovy Teil-Matches innerhalb des Textes finden soll. Soll der ganze String gematched werden wird das in Groovy mit einem ==~ ausgedrückt.
Ah, danke für die Erklärung und wieder was gelernt
 

Ähnliche Java Themen

Neue Themen


Oben