# String zerlegen mittels regulärem Ausdruck



## xray200 (13. Aug 2009)

Hallo zusammen,

ich versuche einen String mit regulären Ausdrücken zu zerlegen, um dann die einzelnen Teile weiterzuverarbeiten.
Mein regulärer Ausdruck ist sehr komplex, aber im Grunde geht es um folgendes (Tokenizer reicht also nicht aus):

Dieses Beispiel funktioniert, ich habe es aus Java ist eine Insel:

String s = "Url := http://java-tutor.com"; 
Scanner scanner = new Scanner( s ).useDelimiter( "\\s*:=\\s*" ); 
System.out.println( scanner.next() );     // Url 
System.out.println( scanner.next() );     // Java Seminare und IT-Schulungen (.NET, XML, Datenbanken, Office und mehr) | tutego

Bei meinen regulären Ausdrücken gibt es kein "\\s*" sondern nur ".+".
Damit scheint es mit diesem Beispiel nicht zu funktionieren, wenn ich aus \\s* schon \\s+ mache, kann ich die einzelnen Teile nicht mehr ausgeben.

Habt ihr eine Idee?


----------



## Michael... (13. Aug 2009)

xray200 hat gesagt.:


> Habt ihr eine Idee?


Nein. Aber wenn Du mal postest wie Dein String aussieht und wie er zerlegt werden soll, kann man Dir sicherlich weiterhelfen.


----------



## bygones (13. Aug 2009)

xray200 hat gesagt.:


> Bei meinen regulären Ausdrücken gibt es kein "\\s*" sondern nur ".+".


du kennst schon den unterschied zwischen den beiden ausdruecken ?

zieg mal den String und den ausdruck die du hast...


----------



## xray200 (13. Aug 2009)

Also mein Ziel ist es, die Zerlegung anhand von RegExs zu machen, da ich diese bereits verwenden, um das Format des String zu prüfen.

Es sind mehrere, ein Beispiel:

(begin.+(weiter.+)*ende.+)

Ich würde nun gern die .+ Teile über Scanner und has next verarbeiten.


----------



## xray200 (13. Aug 2009)

xray200 hat gesagt.:


> Also mein Ziel ist es, die Zerlegung anhand von RegExs zu machen, da ich diese bereits verwenden, um das Format des String zu prüfen.
> 
> Es sind mehrere, ein Beispiel:
> 
> ...



Update: da die obige RegEx so nicht funktioniert, da die Weiter-Teile überlesen werden, nehmen wir einfach nur:

(begin.+ende.+)

Wie kann ich die .+ Teile anhand der RegEx auslesen?


----------



## Michael... (13. Aug 2009)

Habe ich das richtig verstanden Deine Trennzeichen sind 'begin', 'weiter' und 'ende'?
Da ich mit 1.4 arbeite habe ich nicht viel Erfahrung mit der Scanner Klasse
aber da das Teilen mit 
	
	
	
	





```
String.split("begin|weiter|ende")
```
funktioniert, vielleicht funktioniert, dann auch folgendes:

```
Scanner scanner = new Scanner(input).useDelimiter("begin|weiter|ende");
	while(scanner.hasNext()) {
		System.out.println( scanner.next() );
}
```
Ob der String korrekt aufgebaut ist wird ja schon vorher geprüft, oder?


----------



## xray200 (13. Aug 2009)

Michael... hat gesagt.:


> Habe ich das richtig verstanden Deine Trennzeichen sind 'begin', 'weiter' und 'ende'?
> Da ich mit 1.4 arbeite habe ich nicht viel Erfahrung mit der Scanner Klasse
> aber da das Teilen mit
> 
> ...



das Begin, weiter, ende ist nur ein sehr einfaches Beispiel. Ich habe viele RegExs, die sehr komplex sind.
Damit prüfe ich die Syntax und dann möchte ich die einzelnen Teile auslesen.
Es muss nicht die Scanner-Klasse dafür sein, mir gelingt es nur nicht, die Teile, die ich mit ".+" kennzeichne, auszulesen.
Ich nehme an, das funktioniert dann anders. Aber wie?


----------



## bygones (13. Aug 2009)

gruppieren die "Teile" die du haben willst, hol dir einen Matcher und iteriere ueber die matches und deren Gruppe.


----------



## xray200 (13. Aug 2009)

bygones hat gesagt.:


> gruppieren die "Teile" die du haben willst, hol dir einen Matcher und iteriere ueber die matches und deren Gruppe.



Wie würde das an meinem Beispiel konkret aussehen?


----------



## bygones (13. Aug 2009)

funktioniert mit matcher und mit scanner

```
public class K {

    public static void main(String[] args) {
        String s = "Begin hier steht nun irgendwas Weiter was anderes End";
        
        Pattern pattern = Pattern.compile("Begin(.+)Weiter(.+)End");
        Matcher matcher = pattern.matcher(s);
        while (matcher.find()) {
            System.out.println(matcher.group(1));
            System.out.println(matcher.group(2));
        }
        
        Scanner scanner = new Scanner(s);
        scanner.useDelimiter("Begin|Weiter|End");
        while (scanner.hasNext()) {
            System.out.println(scanner.next());
        }
    }
}
```
beim matcher bzw dessen Pattern gibt man halt an was man haben will und beim Scanner was die Begrenzungen sind...


----------



## Wildcard (13. Aug 2009)

Regex: 
	
	
	
	





```
begin(.+?)(weiter(.+?))*ende(.+)
```
Auf die Gruppen (Klammern markieren Gruppen) kommst du dann mit Matcher.group(number)


----------



## Landei (13. Aug 2009)

xray200 hat gesagt.:


> das Begin, weiter, ende ist nur ein sehr einfaches Beispiel. Ich habe viele RegExs, die sehr komplex sind.



Schonmal daran gedacht, einen "richtigen" Lexer zu bemühen? Wenn es *wirklich* komplizierter wird, sind RexEx nur eine besonders schmerzhafte Form des Masochismus, und Parser-Generatorn wie ANTLR, JavaCC usw. das Mittel der Wahl.


----------



## bygones (13. Aug 2009)

Landei hat gesagt.:


> Wenn es *wirklich* komplizierter wird, sind RexEx nur eine besonders schmerzhafte Form des Masochismus, und Parser-Generatorn wie ANTLR, JavaCC usw. das Mittel der Wahl.


ich behaupte mal 90% aller "komplizierten" regex sind normale regex... ansonsten klar


----------



## xray200 (13. Aug 2009)

bygones hat gesagt.:


> funktioniert mit matcher und mit scanner
> 
> ```
> beim matcher bzw dessen Pattern gibt man halt an was man haben will und beim Scanner was die Begrenzungen sind...[/QUOTE]
> ...


----------



## Wildcard (13. Aug 2009)

Mit matches hast du schon die gesamte Eingabe konsumiert. Was soll da für find übrigbleiben?


----------



## xray200 (13. Aug 2009)

Wildcard hat gesagt.:


> Mit matches hast du schon die gesamte Eingabe konsumiert. Was soll da für find übrigbleiben?



Ich möchte zuerst prüfen, ob der komplette String mit der RegEx übereinstimmt und falls ja, dann die einzelnen Teile der RegEx auslesen.

Wie mache ich es dann?


----------



## xray200 (13. Aug 2009)

xray200 hat gesagt.:


> Ich möchte zuerst prüfen, ob der komplette String mit der RegEx übereinstimmt und falls ja, dann die einzelnen Teile der RegEx auslesen.
> 
> Wie mache ich es dann?




```
if (m.find()==true) {	for (int i=1;i<=m.groupCount();i++){
					System.out.println(i);
					ergebnisliste.add(m.group(i));
				}
}
```

Da der gesamte Text der RegEx entsprechen muss, also nur 1x gefunden werden kann, müsste das so passen oder?


----------



## bygones (13. Aug 2009)

find gitb an ob der Regex gefunden wurde, matches gibt an ob er Komplett gematcht hat.

also wenn du restriktiv bist und sagst der string darf NUR komplett vom regex abgedeckt sein dann

```
if(m.matches()) {
  for...
}
```


----------



## xray200 (13. Aug 2009)

OK, dann geht es mit matches. Allerdings bekomme ich bei folgendem RegEx nur die zweite Gruppe ausgegeben.
Die group(i) beginnt doch ab 1, weil 0 doch den gesamten String enthält.

Regex: [^t]+t[e]+e
Beispieltext: 1ct3e

Bekomme ich nur die "3" vor dem e, als group(1), aber nicht 1ct. Warum nicht?


----------



## bygones (13. Aug 2009)

du hast nirgends eine gruppe... man gruppiert mit ( )


----------



## Wildcard (13. Aug 2009)

Dieser RegEx hat gar keine Groups.


----------



## xray200 (13. Aug 2009)

bygones hat gesagt.:


> du hast nirgends eine gruppe... man gruppiert mit ( )



OK, ich kann also nur Gruppen im Sinne von ( ) abfragen.
Wie kann ich eine Gruppe aus Buchstaben bilden, die nicht erlaubt sind, also ginge (^e)+ als Gruppe?


----------



## bygones (13. Aug 2009)

xray200 hat gesagt.:


> Wie kann ich eine Gruppe aus Buchstaben bilden, die nicht erlaubt sind, also ginge (^e)+ als Gruppe?


wenn dann eher [c]([^e]+)[/c]

als tipp - wenn du mit eclipse arbeitest lad dir Eclipse Regular Expression Tester - admit kannst du einfach deine regex testen


----------



## xray200 (13. Aug 2009)

bygones hat gesagt.:


> wenn dann eher [c]([^e]+)[/c]
> 
> als tipp - wenn du mit eclipse arbeitest lad dir Eclipse Regular Expression Tester - admit kannst du einfach deine regex testen



Danke für den Tipp! Teste ich...


----------



## xray200 (13. Aug 2009)

Wie ist es denn mit Verschachtelten Gruppen. Wie reagiert group(i)?
Nimmt es nur die oberste Hierarchieebene der Gruppen oder alle?

Also Bsp: ((e)*)?


----------



## Wildcard (13. Aug 2009)

Zähle die öffnenden Klammern, das ist dann die Gruppennummer


----------



## xray200 (13. Aug 2009)

bygones hat gesagt.:


> wenn dann eher [c]([^e]+)[/c]



Wie wäre es denn bei 2 Buchstaben "cd", als Gruppe, die nicht erlaubt sind:

[c](^cd)+[/c] geht wohl nicht...


----------



## xray200 (13. Aug 2009)

Hat da jemand eine Idee?

Auch [^(cd)]+ geht nicht, c und d werden immer als einzelne Buchstaben behandelt.


----------



## bygones (13. Aug 2009)

meinst du sowas

```
String s = "huhu cdfr cdcd";
        Pattern pattern = Pattern.compile("([^c|d]+)");
        Matcher matcher = pattern.matcher(s);
        while(matcher.find()) {
            System.out.println(matcher.group(1));
        }
```
gibt huhu und fr aus


----------



## xray200 (14. Aug 2009)

bygones hat gesagt.:


> meinst du sowas
> 
> ```
> String s = "huhu cdfr cdcd";
> ...



Aber ich möchte ja "c" und "d" als einzelne Buchstaben nicht eliminieren.
Mit deinem Vorschlag erhalte ich aus ccdd nichts, obwohl ich c und d am Anfang und am Ende ja haben will.
Ich möchte einfach analog zu [^c] also dem Verbot eines Buchstabens, die Buchstabenfolge "cd", undzwar nur diese, verbieten.

Wie mache ich das am besten?


----------



## bygones (14. Aug 2009)

ich muss gestehen ueber Pattern weiss ich das jetzt auch nicht.

mit dem Scanner klappt das

```
String s = "huhu cdfr ccdd";
Scanner scanner = new Scanner(s);
scanner.useDelimiter("cd");
while (scanner.hasNext()) {
    System.out.println(scanner.next());
}
```


```
huhu 
fr c
d
```

ich bezweifle mal dass das aber auch nicht wirklich das ist was du suchst...


----------



## xray200 (14. Aug 2009)

Ich suche zum Ein-Zeichen-Verbot [^c]+ das analoge für mehrere Zeichen als Zeichenfolge, wobei [^(cd)] nicht funktioniert.

Hat da jemand eine Idee, wie man das in RegeEx macht?


----------

