# Reguläre Ausdrücke



## DarXun (2. Mai 2012)

Guten Abend liebe Community.

In der Uni behandeln wir gerade das Thema "Reguläre Ausdrücke" und als Aufgabe sollten wir diese dann auch mal anwenden.

Bisher hatte ich auch keine großartigen Probleme damit, doch bei einer Aufgabe bleib ich einfach hängen und auch meine Kommilitonen wissen nicht weiter.

Die Aufgabe ist folgende:

Es soll ein Ausdruck geschrieben werden, der alle Strings matcht, die ein 'q' oder 'Q' enthalten, dass nicht von einem 'u' gefolgt wird.
Als Testfälle werden dann folgende Worte aufgeführt:

Qantas, Qanquas, Iraq, Quatsch, Test

Qantas und Iraq sollten also matchen, während Qanquas, Quatsch und Test nicht gematcht werden dürfen.

Von der Logik her schien das ja recht einfach. Ich matche alle Wörter, die ein q oder Q enthalten, auf welches *kein* u folgt. Davor und danach können beliebig viele Zeichen folgen.

Mein erster Ansatz war damit: ".*[qQ][^u].*"
Dabei wird aber auch Qanquas gematcht und Iraq nicht.
Iraq wird wohl nicht gematcht, da ich ja ein von u verschiedenes Zeichen wollte... Es wird also ein Zeichen erwartet.
Das Problem mit Qanquas habe ich mir folgendermaßen erklärt:
Das erste Q wird erkannt. Auf dieses Q folgt kein u, weswegen das folgende qu nicht beachtet wird.

Um das qu in Qanquas aber auch zu erkennen habe ich es mit folgendem Ausdruck versucht.
"[.*[qQ][^u].*]+"
Damit sollte der bisherige Ausdruck ja öfters angewandt werden, soweit ich das mit dem + verstanden habe (wobei ich mir nicht sicher bin oder man die [ ] auch auf einen ganzen Ausdruck anwenden kann, wie ich es hier gemacht habe).

Mit diesem Ansatz habe ich aber das Problem, dass auch Test gematcht wird.
Wieso das hier passiert ist mir ein Rätsel.

Habt ihr andere Ideen oder Tips für mich?
Ich möchte natürlich nicht das jemand mir das einfach löst, schließlich bleibt es ja meine Aufgabe und durch eine Lösung wäre ich auch nicht schlauer.
Ein kleiner Stoß in die richtige Richtung könnte aber von Nutzen sein.

Mit freundlichen Grüßen,

DarXun


----------



## SlaterB (2. Mai 2012)

mit eckigen Klammern machst du eine Auswahl, für Wiederholung ganz außen runde Klammern nehmen,

.* ist schlecht, da können auch bei Wiederholung noch beliebige lange Teile drin untergehen, matche an diesen Stellen nur Bestandteile ohne q-s,
damit sichergestellt ist, dass jedes q in dem mittleren Teil drankommt

schließlich noch q am Ende, da musst du zu einem ^u-Zeichen eine Alternative einbauen, Wortende,
daran kannst du ja noch knobeln, sonst verrate ich es morgen, das ist ja reines Syntax-Wissen

muss eigentlich auch "Qqu" verhindert werden? das wäre einen Tick komplizierter.., kannst du ja in deine Testfälle aufnehmen


----------



## Tomate_Salat (2. Mai 2012)

Hat en bissl gedauert, aber ich habs raus. 

Als hilfe: ich hab mit negative-look-behinds gearbeitet. Damit + Slaters tipps geht es relativ einfach.

-----

Ergebnis für folgende Tests:

```
String[] tester = {
	"Qantas",
	"Qanquas",
	"Iraq",
	"Quatsch",
	"Test",
	"Qqqqustottermeister"
};
for(String t:tester) {
	System.out.println(t + " matches: " + t.matches(regex));
}
```


```
Qantas matches: true
Qanquas matches: false
Iraq matches: true
Quatsch matches: false
Test matches: true
Qqqqustottermeister matches: false
```


----------



## DarXun (2. Mai 2012)

EDIT:

Bis auf das qqu Problem habe ich's jetzt, allerdings ohne negative-look behinds.
"([^qQ]*[qQ]([^u]|$)[^qQ]*)+$"

Wenn ich die negative-look behinds richtig verstanden habe, dann schaue die sich die U-s an gucken ob davor ein q steht. Wenn dem so ist wird nicht gematcht.
Wenn ich das entsprechend in den Ausdruck einbauen würde dann müsste er auch die qqu's nicht mehr matchen...

MfG

DarXun

--------


Hi.

Danke schon mal für die Antwort.

Das mit dem [^qQ]* war schonmal klasse. Vielen Dank.
Mein Ausdruck sieht jetzt folgendermaßen aus:

([^qQ]*[qQ][^u][^qQ]*)

Damit werden die q's schonmal im Mittelteil erst abgefangen.
Als nächstes versuche ich mich mal an Qanquas.

Das mit dem q am Ende habe ich noch nicht herausgefunden bisher.
Ich bemühe mich selbstverständlich weiterhin.

Mit freundlichen Grüßen,

DarXun


----------



## HoaX (3. Mai 2012)

Ich komme auf 
	
	
	
	





```
Qantas: true
Qanquas: true
Iraq: true
Quatsch: false
Test: false
Qqqqustottermeister: true
```

Wobei die Aussage 





DarXun hat gesagt.:


> Qantas und Iraq sollten also matchen, während Qanquas, Quatsch und Test nicht gematcht werden dürfen.


 der Aufgabenstellung widerspricht. Qanquas hat ja ein Q ohne u, also sollte das auch matchen.

Kurz und knapp (?i)q(?=[^u]|\$)

q oder Q, gefolgt von: "nicht u" oder Ende der Zeichenkette.


----------



## DarXun (3. Mai 2012)

Qanquas hat aber auch ein qu, weswegen es nicht gematcht werden soll.
Habe ich mich wohl falsch ausgedrückt, sorry.
Tomate hat scheinbar schon die entsprechende Lösung, aber mit den negative-look behinds haben wir noch nicht gearbeitet und so recht verstehen tu ich die auch noch nicht.

Hätte jemand dazu noch eine Erläuterung/ein Tutorial?


----------



## SlaterB (3. Mai 2012)

> Qanquas hat aber auch ein qu, weswegen es nicht gematcht werden soll.

so schlau, um das zu erkennen ist jeder, auch ein Hoax, das kannst du dir sicher denken,
also wenn du schon was dazu sagen willst, dann überlege, was Hoax wohl gemeint haben könnte

das ist nämlich folgendes:
"Es soll ein Ausdruck geschrieben werden, der alle Strings matcht, die ein 'q' oder 'Q' enthalten, dass nicht von einem 'u' gefolgt wird."

Qanquas IST ein String, der ein 'Q' enthält welches nicht von einem 'u' gefolgt wird, 
es geht in deinem Satz, der wohl nicht der offizielle Laut der Aufgabenstellung ist, NICHT um ALLE Vorkommen von Q-s, sondern nur um EIN Vorkommen, Rest egal

(edit: durch deinen edit ist es bisschen deutlicher geworden als nur die erste Zeile)


----------



## HoaX (3. Mai 2012)

Vielleicht wäre es sinnvoll mal die originale Aufgabenstellung zu posten?!


----------



## DarXun (4. Mai 2012)

Hallo.

Eine Lösung ohne negative-look behinds habe ich mittlerweile entwickeln können.

(?i)(q+[^uq]|[^q])*(q+([^uq]|$))(q+[^uq]|[^q])*

Wegen der Aufgabenstellung:

Ich habe mich wohl falsch ausgedrückt.
Es soll kein qu vorkommen dürfen.

Hier der Originaltext:

Erweitern Sie den regulären Ausdruck aus Aufgabe II so, dass er ganze Wörter matcht, in denen "q" nicht von "u" gefolgt wird. Wörter, in denen zwar ein "q" vorkommt, dass nicht von einem "u" gefolgt wird, die jedoch zusätzlich auch ein "qu" enthalten sollen nicht gematcht werden.

Der Ausdruck aus Aufgabe II lautete:
(?i).*q([^u]|$).*

Wie gesagt. Aufgabe ist erstmal gelöst. Mal schauen ob ich auch mit den look-arounds das ganze handhaben kann.
Vielen Dank für die Hilfe

DarXun


----------

