Regexp ... Einstieg sinnvoll?

Hallo!

\S*a\S*
und
[a-z]*[a][a-z]*

… liefern bei mir identische Ergebnisse.

Aber nicht bei Wörtern wie „5-fach“ oder „nimm2“.
\s steht für ein sog. Whitespace, z.B. Leerzeichen, Tabs.
\S steht für alles aus \s, ist also die Umkehrung.

Ich sehe noch nicht mal ansatzweise eine Ähnlichkeit.

„Wort“ mit genau einem a:
(^|\s)[^a\s]*a[^a\s]*(?=(\s|$))

Das Blöde ist, dass ein Wort eben nicht nur von Leerzeichen eingeschlossen sein kann, sondern auch am Anfang oder am Ende stehen kann. Wenn wir jetzt einfach mal unseren Text vorne und hinten vorher um ein Leerzeichen ergänzen würden - kann man ja machen - wäre der Regexp schon deutlich einfacher.
\s[^a\s]*a[^a\s]*\s
Liest sich: ein Leerzeichen (eigentlich Whitespace), gefolgt von einer beliebigen Anzahl von Zeichen, die kein Leerzeichen oder „a“ sein dürfen, gefolgt von einem „a“, gefolgt von wieder einer beliebigen Anzahl von Zeichen, die kein Leerzeichen oder „a“ sein dürfen, gefolgt von einem Leerzeichen.

Das auf z.B. " einsa azwei drai " angewandt (man beachte die Leerzeichen am Anfang und Ende), sollte " einsa ", " azwei " und " drai " liefern. Sollte, erkennt aber nur " einsa " und " drai ". Warum? Weil nach dem Erkennen von " einsa " der ‚Lesezeiger‘ (keine Ahnung, wie man den richtig nennt) hinter dem erkannten Teil steht, also vorm „a“ von „azwei“. Das ist dumm, denn unser Regexp verlangt als erstes ein Leerzeichen (\s), das aber schon hinter uns liegt. Und so wird erst wieder " drai " erkannt.

Und da kommt jetzt dieses (?=\s) zum Einsatz (\s[^a\s]*a[^a\s]*(?=\s)). Das nennt sich Lookahead (Vorgriff) und bewirkt, dass für das erkannte Leerzeichen der Zeiger nicht weitergerückt wird, sondern quasi die Regexp-Engine einen langen Hals macht und guckt, ob dann denn vielleicht ein Leerzeichen kommt. Wenn ja, bleibt aber der Zeiger, wo er war, also vorm Leerzeichen und " azwei " kann erkannt werden.

Und das kann Jemand lesen und verstehen?
Das schaffe ich nie. :frowning:

Ok, das ist natürlich alles auf einmal viiiiiel zu viel. Lookahead habe ich sicherlich lange nicht genutzt, weil nicht gekannt. Wir waren in der IT-Ausbildung gezwungen, den vi, den du ja kennst, zu benutzen. Wir alle haben gestöhnt. Da hab ich mir gesagt, das Teil lernst du jetzt, besonders so Sachen, wie „Suchen und Ersetzen“. Das war der Einstieg ins Thema Regexp, aber kein Einstieg von heute auf morgen.

Jan

Hallo allerseits,
erst mal entschuldigung, dass ich mit den Schrägstrichen verwirrt habe.
Ich kenne auch Sprachen, wo die Zusatzoptionen(wie „ignore case“ oder „global“) nicht im Ausdruck codiert werden.
Jetzt wo ich weiß, dass es in VB auch nicht so geht, verzichte ich im Weiteren auf solche Optionen.

Noch was Grundlegendes:

a* bedeutet keins oder beliebig viele „a“ in Folge
a+ bedeutet mindestens ein oder beliebig viele „a“ in Folge
a{3} bedeutet genau 3 „a“ in Folge
a{2,5} bedeutet zwischen 2 und 5 „a“ in Folge

Eine eckige Klammer wie [a-guwx] ist eine Zeichenklasse,
die alle in ihr stehenden Zeichen(-bereiche) zusammenfasst,
zu einem einzigen Zeichen.
Also wenn er ein Zeichen anguckt, dann wählt er sich ein beliebiges aus der Klammer, um den Ausdruck zu erfüllen.
Dasselbe könnte man auch mit ODER-Verknüpfung erreichen:
[a-guwx] ist gleich (a|b|c|d|e|f|g|u|w|x)

Wie kann ich alle Wörter ausgeben, die ein a enthalten
und kein e

Schnellschuss: [a-df-z]*a[a-df-z]*

Wenn wenn ein „Wort“ etwas ist mit Leerzeichen drumherum:
[^e\s]*a[^e\s]*

Mit beiden Ausdrücken das selbe Ergebnis, mit beiden Varianten
werden die Wörter nicht komplett ausgegeben, sondern nur bis
zum ‚a‘.

Die Enthalten ja auch beide logische Fehler :wink:
Ich versuche die mal aufzuklären:

  1. Schnellschuss:
    [a-df-z]*a[a-df-z]*
    Reguläre Ausdrücke werden immer von links nach rechts ausgewertet.
    Der Stern * „frisst“ ALLES auf was dem entspricht was vor ihm steht.
    Man nennt den Stern deshalb „gierig“ oder „greedy“.
    Beispiel:
    aalfisch
    Auf den Ausdruck:
    [a-df-z]*
    passt „aa“, dann kommt „l“, das passt nicht und er geht zum nächsten Muster nämlich a aber es gibt kein „a“ sondern nur „l“ an dieser Stelle und er bricht ab.
    Nur weil der Stern so gierig ist :wink:

  2. Schnellschuss:
    [^e\s]*a[^e\s]*
    aalfisch
    auch hier! [^e\s]* frisst alles was kein „e“ und kein Leerzeichen ist, also auch das a.
    „aalfisch“ wird komplett geschluckt, doch dann folgt wieder kein weiteres „a“ wie im Muster angegeben. -> abbruch
    Und der gierige Stern hat wieder alles vertilgt :wink:
    Merke:
    Verwende den gierigen Stern nur, wenn das davorstehende und das darauffolgende Muster sich gegenseitig ausschließen.
    Weder [a-df-z] und a, sowie noch [^e\s] und a schließen sich aus!

Eine Lösung die funktionieren sollte:
\s[^ea]*a[^e]*\s
Findet nach einem Whitespace, alles was weder „e“ noch „a“ ist,
dann ein „a“, dann alles was kein „e“ ist und ein Whitespace.
Somit steht zwischen den Whitespaces ein Wort mit mindestens einem „a“ und keinem „e“.
Man beachte [^ea] und a schließen sich aus.
Der Stern frisst sich nur bis zum ersten a durch, dann gehts weiter.

kanibal wird also wie folgt erkannt:
[^ea]* schluckt nur „k“
a schluckt „a“
[^e]* schluckt den Rest „nibal“

Man kann auch das „gierige“ Verhalten von Stern * und Plus + abschalten, in dem man ein Fragezeichen dahinter angibt.
z.B.
[^e\s]*?
Jetzt frisst der Stern so wenig wie möglich, damit der gesamte Ausdruck erfüllt ist.
also müsste auch:
[^e\s]*?a[^e\s]*
funktionieren.

Mein versuch hatte so ausgesehen:

[a-df-z]*[a][a-df-z]*

Da passiert aber auch nichts anderes.

Weil es ja auch semantisch dasselbe ist :wink:

Ich hoffe ich konnte diesmal etwas Licht in den Tunnel bringen.

Beste Grüße
VoidZer0

Hallo!

Man nennt den Stern deshalb „gierig“ oder „greedy“.
Beispiel:
aalfisch
Auf den Ausdruck:
[a-df-z]*
passt „aa“, dann kommt „l“, das passt nicht

Natürlich passt l. Ist doch in [a-df-z] enthalten.

und er geht zum nächsten Muster nämlich a aber es gibt kein „a“ sondern nur
„l“ an dieser Stelle und er bricht ab.

Nein, das ist falsch. [a-df-z]* frisst alles bis zum h. Dann kommt a, passt aber nicht und die Engine gibt sukzessive Zeichen wieder frei, h ,c ,s ,i ,f ,l ,a und - hurra - das a wird erkannt und ist erledigt und das zweite [a-df-z]* ist dran und frist den Rest „lfisch“.

Nur weil der Stern so gierig ist :wink:

Was du beschreibst, gierig ohne zurückzugeben, heißt „possessive quantifier“, *+, ++ und ?+. Kennt aber VB6 nicht.

Der einzige Fehler meines Regexps ist, dass auch „Aalfisch“ auch erkannt wird, wenn der Text „Aalfische“ lautet.

Ich glaub’, machen hier gerade „Reguläre Ausdrücke zum Abgewöhnen“ und sollen vielleicht Wochenende machen :wink:

Jan

Nein, das ist falsch. [a-df-z]* frisst alles bis zum h. Dann
kommt a, passt aber nicht und die Engine gibt sukzessive
Zeichen wieder frei, h ,c ,s ,i ,f ,l ,a und - hurra - das a
wird erkannt und ist erledigt und das zweite [a-df-z]* ist
dran und frist den Rest „lfisch“.

Nur weil der Stern so gierig ist :wink:

Was du beschreibst, gierig ohne zurückzugeben, heißt
„possessive quantifier“, *+, ++ und ?+. Kennt aber VB6 nicht.

Oh verdammt! Stimmt! Ich bin auch schon total Betriebsblind!

Der einzige Fehler meines Regexps ist, dass auch „Aalfisch“
auch erkannt wird, wenn der Text „Aalfische“ lautet.

Ja aber wie du gezeigt hast ist er nicht sehr effizient,
da der Stern trotzdem gierig ist.
Einigen wir uns darauf, dass der folgende Ausdruck den Fehler behebt und effizient funktioniert:
\b[^ea\s]*a[^e\s]*\b

Getestet mit:
„Kann man einen Aalfisch oder mehrere Aalfische bei Ihnen essen?“
Ergebnisse:

  1. Kann
  2. man
  3. Aalfisch

Ich glaub’, machen hier gerade „Reguläre Ausdrücke zum
Abgewöhnen“ und sollen vielleicht Wochenende machen :wink:

Oh ja ich glaub’ die Wochenendsmüdigkeit bricht aus!
Besser is’ :wink:

Hallo!

Einigen wir uns darauf, dass der folgende Ausdruck den Fehler
behebt und effizient funktioniert:
\b[^ea\s]*a[^e\s]*\b

Ah, hast das fehlende \s aus deinem vorhigen Vorschlag noch bemerkt. Das sieht gut aus, auch wenn \b nicht unserer aktuellen Wortdefinition entspricht. Mein Vorschlag irgendwo im Thread-Nirwana mit dem Lookahead sollte dafür funktionieren, wenn man die e-Geschichte da noch einbaut.

Jan

Oh wohl wahr ein echter Jungel voller Hickhack…
wir hätten einfach einen Link auf ein gutes Tutorial posten sollen und gut. *g*
Sogar der Wikipediaeintrag ist gar nicht schlecht:
http://de.wikipedia.org/wiki/Regul%C3%A4rer_Ausdruck
(jedenfalls besser als das hier :smiley:)
und hier was zum einfachen Testen:
http://www.regexe.de/
Der Ausdruck sollte jetzt zumindestens das Gewünschte leisten,
auch wenn ich nicht weiß wie eure Wortdefinition aussieht.
(Bei mir ist ein Wort immer sowas hier \b(\w+)\b).

In diesem Sinne ein schönes reguläres Wochenende ohne reguläre Ausdrücke :wink:

Beste Grüße
VoidZer0