Regexp in VB - ein kleines How To

Für mein letztes Projekt habe ich auch immer wieder Reguläre Ausdrücke gebraucht, da sonst das Auslesen bestimmter Werte unmöglich gewesen wäre.
Wer wissen will, was Reguläre Ausdrücke sind findet im Wikipedia eine gute Anlaufstelle.
Da es leider auch sehr viele unterschiedliche Implementierungen gibt, gehe ich mal auf die VB.NET Variante ein. Diese dürfte auch in allen anderen .NET Sprachen funktionieren, aber garantieren tue ich es nicht.

Übrigens eine gute Einstiegshilfe für Reguläre Ausdrücke gibts bei txt2re.com

Stell dir vor, du hast ungefähr immer gleiche bzw. ziemlich ähnlich aufgebaute Textzeilen, die sich wiederholen.

000010 02.123.7421.0       BUCHSENKONTAKT   4                                                QMM
       Ihre Artikelnummer: 21076
                      200 ST          20,83 EUR                                     /   100      ST                               41,66
       Sonderrabatt 1                 60,00-%                                                                                     25,00-
       Positionsnetto                  8,33 EUR                                     /   100      ST                               16,66
        ST
       Liefertermin (Tag): 25.02.2010

Nun sollst du diese Nummer heraus extrahieren: 02.123.7421.0
Der Aufbau der Ziffern ist immer gleich. Nur vorne kann auch mal ein Buchstabe vorkommen: also Z7.123.1234.0

Der reine Reguläre Ausdrück wäre wie folgt:

((\w{1}\d{1}|[0-9]{2})\.[0-9]{3}\.[0-9]{4}\.[0-9]{1})

1. Ziffernbereiche und Buchstabenbereiche mit Mengenangaben
Trennen wir also mal den Ausdruck auf: "(\w{1}\d{1}|[0-9]{2})\." (natürlich ohne die Gänsefüsschen " gesehen) ist eine Oder Bedingung. Zuerst wird gesucht, ob ein Buchstabe und eine Zahl nacheinander stehen ("\w{1}\d{1}" ) oder eben zwei Ziffern ("[0-9]{2}" ) und davon zwei Stück nacheinander stehen. Der obligatorische Punkt wird durch die Kombination \. dargestellt! Ein einzelner . würde in diesem Fall für ein beliebiges Zeichen stehen und das wäre ungeschickt. Um also nur den . zu finden, muss dieser noch maskiert werden durch ein Backslash \ gefolgt von dem . also eben \.
Eine vollständige Erklärung für solche Metazeichen gibts hier

Die anderen Zeichen wie "[0-9]{3}\." sind dann sicher recht einfach. In den eckigen Klammern [] steht der Ziffernbereich (es könnte auch [025] stehen, dann wären nur die Ziffern 0, 2 und 5 erlaubt) und in den geschweiften Klammern die Anzahl der Ziffern. Zu guter Letzt muss die Ziffernfolge wieder durch ein . beendet werden, bis die nächste Ziffernfolge folgt.

Diese Zeichenkette findet man sicher noch relativ leicht, da sie ziemlich eindeutig ist.

2. Ziffernbereiche (bzw. jede beliebige Bereichsgruppe) und min und max Angaben
Du willst aus dem oben gezeigten Text die Artikelnummer herausextrahieren.
Leider kann diese Artikel aus allen beliebigen Ziffern bestehen und entweder 5 oder 6 Ziffern haben.

Doch eine Regelmäßigkeit gab es: "Ihre Artikelnummer: 21076" Es steht immer der gleiche Text vor der Artikelnummer, nämlich: Ihre Artikelnummer
Warum also nicht ein Regexp schreiben und der die gesamte Zeichenkette (also Text plus Nummer) beinhaltet. Gesagt getan, hier also der Reguläre Ausdruck:

Dim re1 As String = ".*?"           'Non-greedy match on filler
Dim re4 As String = "(Ihre Artikelnummer: [0-9]{5,})"    'Word 3
Dim r2 As Regex = New Regex(re1 + re4, RegexOptions.IgnoreCase Or RegexOptions.Singleline)

So sieht also auch mal eine Beispielsyntax für die Verwendung der Regexp in VB aus. Für die Bedeutungen von IgnoreCase und Singleline gibts hier von Microsoft eine Erläuterung.
IgnoreCase beachtet also die Groß und Kleinschreibung, wenn das Muster gefunden wurde und Singleline gibt dem . die Bedeutung "alle Zeichen".

Der obige Ausdruck sucht nach dem Text "Ihre Artikelnummer: " und einer Nummer mit 5 Ziffern bzw. mehr Ziffern "[0-9]{5,}" Man kann in den geschweiften Klammern nämlich eine Mindestanzahl und eine Maximalanzahl angeben. Die Mindestanzahl steht vor dem Komma und die Maximalanzahl nach dem Komma.

Um also den regulären Ausdruck auch auszuwerten benötigen wir noch weiteren Code.

Dim m2 As Match = r2.Match(txt)     'txt ist eine ausgelesene Zeile
                If (m2.Success) Then                'h-team Nummer
                    Dim word3 As Group = m2.Groups(1)
                    'erste zwanzig Zeichen sprich "Ihre Artikelnummer: " abschneiden
                    Dim hteam As String = word3.ToString.Remove(0, 20)
                    exWS.Range("D" & zählerb - 1).Value = hteam 'Damit wird der Wert in Excel geschrieben. Kann aber auch jeder beliebe andere Befehl verwendet werden.
                End If

Das ist soweit also auch noch klar.

3. Bestimmter Preis in einer bestimmten Zahl finden
Doch nun wollen wir den Preis in der Positionszeile erwischen, das war damals für mich eine ernsthafte Herausforderung und nur dank diesem Forumseintrag habe ich endlich eine Lösung gefunden.

Und er hat es auch ziemlich gut beschrieben, deshalb möchte ich es gerne hier zitieren:

So geht's:

Zunächst testen ob in der Zeile steht: Das Wort  Positionsnetto gefolgt von     einem oder mehreren Zeichen bis die Zeichenfolge      ST kommt und auf diese wieder      ein oder mehrere Zwischenraumzeichen folgen.

Dann muß man noch berücksichtigen, daß der gesuchte Betrag mehrere Tausenderpunkte haben kann , z.B.     12.345.678,90  und immer genau 2 Dezimalstellen hat.

Das Suchmuster muß also so aussehen:

        Dim re7 As String = "(?<=Positionsnetto.+ ST\s+)([0-9]{1,3}.)*[0-9]{1,3},[0-9]{2}"   'word 5

Na alles klar? Zuerst wird also nach der Zeile gesucht, in der "Positionsnetto" vorkommt, dann dürfen ein oder mehere beliebige Zeichen vorkommen ".+" , dann folgt ST, dann wieder ein oder mehrere Zwischenraumzeichen "\s+" und dann kommen die Zahlen. Das ist oben schon ziemlich gut erklärt.

4. Als nächstes war noch die PE herauszufinden, dass ist eigentlich relativ leicht und ist im Prinzip nur eine abgewandelte Regexp von oben. Da ich es auch im Forum schon geschrieben habe, hier die Erklärung dazu:

Erstmal wieder danke, durch deine Erklärungen hat sich mir  dann auch das Suchmuster für die PE (1 oder 100) erschlossen.

Hier das Suchmuster, dass ich zuerst ausprobiert habe.

Dim re8 As String = "(?<=Positionsnetto.+ EUR\s+/\s+) [0-9]{1,3}" 'word 7

Das hat aber dann nicht genau hingehauen, da damit zwar

Positionsnetto                  8,33 EUR                                     /   100      ST                               16,66

und

Positionsnetto                 71,66 EUR /                                   100    ST                              71,66

abgedeckt waren.

Aber solche Zeilen wie diese hier:

Positionsnetto                  41,09 EUR / 100 ST                                                            82,18

wurden verworfen.

Also habe ich nun folgendes Suchmuster angewendet:

Dim re8 As String = "(?<=Positionsnetto.+ EUR.+) [0-9]{1,3}" 'word 7

Sprich in der Zeile muss das Wort Positionsnetto gefolgt von einem oder mehreren Zeichen bis die Zeichenfolge EUR kommt und auf diese wieder  ein oder mehreren Zeichen folgen und dann eine Zahl mit 1 oder 3 Ziffern (also entweder 1 oder 100).

Nur so als Hilfestellung, falls jemand mal ähnliche Probleme hat.

5. Und zu guter letzt wäre natürlich auch noch der Liefertermin interessant.

Dieser ist eigentlich ziemlich logisch aufgebaut. "Liefertermin (Tag): 25.02.2010"
Doch leider kommt es auch vor, dass "Liefertermin unbestätigt" drin steht.
Aber auch hier gab es wieder Hilfe von diesem Peter_Punkt:

So geht's:

Bei dieser Aufgabenstellung treten gleich mehrere Probleme auf:

Umlaute im Suchmuster (z.B. ä) sind nicht erlaubt.

Klammer () haben eine besondere Bedeutung. Wenn man sie als normale Zeichen behandelt wissen will, dann muß man \ voranstellen.

Außerdem muß man die erzielten Treffer nachbehandeln und Teile (z.B. "(Tag): ") entfernen.

Code-Beispiel:

Dim re6 As String = "(?<=Liefertermin )(\(Tag\): \d{2}\.\d{2}\.\d{4})|(unbest){1}"
            Dim r2 As Regex = New Regex(re6, RegexOptions.IgnoreCase Or RegexOptions.Singleline)
            Dim m2 As Match = r2.Match(txt)     ' In txt ist der zu untersuchende String

            If (m2.Success) Then
                Dim word3 As Group = m2.Groups(0)
                Dim treffer As String = word3.ToString
                If treffer = "unbest" Then      ' bis zum ä
                    treffer = "unbestätigt"
                Else
                    treffer = treffer.Replace("(Tag): ", "") ' den Vorspann vor dem Datum entfernen
                End If
                Debug.WriteLine(treffer)
            End If

Man sieht also: Reguläre Ausdrücke sind eine tolle Sache, da man sich damit viel Arbeit ersparen kann. Doch ohne Hilfe in konkreten Problemstellungen ist man ganz schön aufgeschmissen.
Ich hoffe, ich konnte dem einen oder anderen vielleicht eine kleine Hilfestellung sein.
Falls Verbesserungsvorschläge vorliegen. Einfach Kommentar posten und ich werde es korrigieren.

Zirkusfestival, Clarkrevival und Aufnahme im Süddeutschen Gemeinschaftsverband Calw

Das letzte Wochenende war ziemlich voll, aber auch insgesamt gesehen doch schön.
Angefangen hat alles am Freitag mit dem Besuch des Calwer Zirkusfestivals der Zirkus AG der Realschule Calw. Dies war nun mehr schon die 3. Aufführung und ich muss sagen: Mir hat es immer noch gefallen und ich war teilweise ziemlich verblüfft. Zu sehen gab es einige bekannte Tricks. Zum Beispiel der mit der Box und der Frau, die mit Spießen durchbohrt wird und hinterher wieder lebendig herauskommt. Kunststücke mit dem Diablo, Tänze und allerlei Akrobatik war auch geboten. Es lässt sich schlecht in Worte fassen, doch mir und meinen Brüdern hat es sehr gut gefallen.
Auf der Seite gibt es aktuell einige Bilder von der Show: www.zirkus-ag.de

Am Samstag ging es dann gleich wieder früh (9 Uhr) weiter mit der Abfahrt nach Hemmingen zum Clark-Revival vom SV-EC Landesjugendverband. Geboten war einiges: Eine Predigt von Thorsten Hebel zum Thema: "Das Wort, das gelebt werden will" und später eine Predigt zum Thema "Das Wort, das unter Druck standhält".
Also wie man Leuten, die gute Nachricht weiterzählen kann und wie man auf Kritik zur Bibel richtig umgehen kann. Denn die Bibel ist schon alt und vieles kann man angreifen und kann missbraucht werden. Da waren einige Punkte dabei. Vielleicht kommt ja irgendwann noch die MP3 zu den Predigten heraus, dann kann man diese nochmal anhören!
Mit dabei war natürlich auch eine "Worshipband", die aber doch ziemlich rockig abging. Manche meinen, die Frau hätte eine bescheidene Stimme gehabt, doch ist alles Geschmackssache. Da hab ich nicht so draufgeachtet. Habe mich über die Melodien gefreut und dann öfters mal auf den Text konzentriert und ab und an mal mitgesungen. Die Band heißt übrigens "WeckleCross", so hat zumindest der Thorsten Hebel die Band abends nach seiner Comedy angekündigt!
Apropos Comedy: Der Thorsten Hebel hat abends noch nach der Weihestunde (war auch mal gut!) eine Comedy gemacht. Manchen hat es nicht gefallen, den meisten aber schon. Einzelheiten darüber zu erzählen ist schwierig, stellt euch einfach Mario Bart vor. So ähnlich war es, nur ein bisschen anders und teilweise lustiger.

Eine Situation ist genial gewesen:

Da war Thorsten mit seiner Frau in einer U-Bahn in Berlin. Das Abteil war voll, aber keiner hat geredet. Jeder schaute aus dem Fenster. Thorsten fand das komisch und wollte mal Leben in die Situation bringen. Also sagte er: "Wirsingauflauf". Seine Frau hat sich gleich weggedreht und so angedeutet, dass sie nicht dazugehöre. Doch auf einmal war wieder Leben in der Bude. Die einen hielten ihn für verrückt, die anderen lachten, teilweise wurden sogar Rezepte ausgetauscht.

Siehste: So schnell bringt man Leben in eine ruhige Situation.

Und nun zum letzten Punkt: Ich gehe ja schon seit längerem in die Gemeinde in Calw (liebevoll das Säle genannt!), aber Mitglied war ich bisher noch nicht. Also wurde ich angefragt und zusammen mit dem Peter wurde ich nun am Sonntag im Gottesdienst vor versammelter Mannschaft aufgenommen. An und für sich nichts besonderes, aber es war schon irgendwie "aufregend".
Nun darf ich nicht nur weiterhin die Kasse für den EC führen, sondern auch mitbestimmen was gemeindemäßig so ansteht.

So und das war mein Wochenende. Lang und voll, aber dass musste auch mal sein.

Habe Schulplatz fürs BKFH

Vor einiger Zeit habe ich ja mal laut darüber nachgedacht, ob sich die FH-Reife heutzutage noch lohnt. Da gab es verschiedene Meinungen und auch der Vorschlag von meinem Kollegen, dass man ja auch ohne Schule studieren kann.
Ich habe mich aber nun eben doch anders entschieden und mich für einen Platz an der Gottlieb-Daimler-Schule in Sindelfingen beworben.
Gestern kam dann endlich der Bescheid, dass sie mich aufnehmen und dass sie aufgrund der hohen Anzahl an Bewerbern sogar eine zweite Klasse aufgemacht haben. In einer extra gegründeten gGmbH. Ob das nun gut oder schlecht, weiß ich nicht. Aber allgemein gilt: Die Lehrer sind dort recht gut, und manche kenne ich auch noch aus meiner Ausbildung.

Es gab ja die Möglichkeit Technik oder BWL zu wählen. Aufgrund meiner fehlenden Physikkenntnisse und Faulheit habe ich mal BWL gewählt. Das ist aber auch kein Nachteil, denn das meiste, was dort dran kommt habe ich auch schon mal in der Ausbildung gehabt und dort war ich in BWL nicht gerade schlecht.
Soviel mal dazu. Am 21. April ist noch eine Informationsveranstaltung und im September gehts dann los mit der Abendschule.
Was ich dann nach der Schule mache: Keine Ahnung, aber irgendwas studieren wäre sicher nicht verkehrt. Andernfalls habe ich ja immer noch meinen Job, denn ich freiwillig nicht aufgeben möchte.

Winnetou Häberle

Mal zur Abwechslung ein Witz:

Ein Mann und eine Frau sitzen in einem Flugzeug nebeneinander. Sie kommen ins Gespräch und die Frau erzählt, dass sie Sexualwissenschaftlerin sei.
Da fragt der Mann ganz interessiert, welches Volk denn die besten Liebhaber seien.
Die Frau dann so: "Die Indianer haben von allen Völkern auf der Welt das größte Geschlechtsteil! Die Schwaben seien aber für ihre Ausdauer im Bett bekannt."
Darauf meint der Mann zur Frau: "Darf ich mich vorstellen. Winnetou Häberle ist mein Name"

Es darf auch ruhig gelacht werden.

Und noch ein Video dazu: