# Groovy: Verständnis eines regulären Ausdrucks



## Studdi23 (23. Feb 2014)

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:

```
// 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

```
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 (23. Feb 2014)

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+)*




```
~
```
das Zeichen ~ Wenn du Start der Zeile meinst, das ist ^

```
(
```
Hier beginnt eine Capturing group, die alles bis zur schliessenden Klammer umfasst

```
\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

```
\W
```
alles was nicht Word-Character ist, also beispielsweise Leerzeichen

```
+
```
 1-mal oder mehrmals also sind wir bei "John "

```
)
```
Capturing group Ende

```
*
```
 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 (23. Feb 2014)

turtle hat gesagt.:


> ```
> *
> ```
> 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:

```
^((\w*\W+)*(\w*)?)$
```


----------



## turtle (23. Feb 2014)

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 (23. Feb 2014)

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.


----------



## turtle (23. Feb 2014)

> 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


----------

