Entwickler-Ecke
Basistechnologien - Multiline Regexes
bergrath - Di 18.12.07 12:45
Titel: Multiline Regexes
Hi Leute.
Hab da mal ne Frage: Und zwar würde ich gerne wissen wie man einen Regex-Ausdruck sucht der über 2 oder mehr Zeilen geht. Bisher habe ich immer nur Regex-Ausdrücke verwendet, die sich auf eine Zeile beziehen. Nun muss ich Ausdrücke suchen, die über 2 Zeilen gehen.
Ich gebe euch hier mal ein kleines Beispiel, weil ich echt keinen Schimmer habe, wie das zu realisieren ist:
MSDV 011060 CC 01 *** LESS TELEPHONE PREP PACK *** IECAA +SWKV
MSDV 011070 30 01
23D-SWKM-SWKN-SWKO-SWKP-SWKQ-SWKR-SWKS-SWKT-SWKU-SWD6-SWD5-SWD4-SW
MSDV 011070 30 02
D3-SWD2-SWD1-SWCB-SWC9-SWC8-SWC7-SWC6-SWC5=SWKV$
Der fett markierte Teil ist ein zusammenhängender Ausdruck und für diesen Ausdruck möchte ich ein Pattern formulieren, das genau diesen markierten Teil matcht. Die nicht fett markierten Teile sollten nicht berücksichtigt werden.
Für Tipps und Hinweise wäre ich sehr dankbar.
MfG
Moderiert von
Christian S.: Topic aus C# - Die Sprache verschoben am Mi 19.12.2007 um 14:26
bergrath - Mi 19.12.07 09:01
Hi.
Kann mir jemand erklären wie ich Matches über mehrere Zeilen erhalten kann? Was ist der Unterschied zwischen Singleline und Multiline???
Danke für eure Antworten im Voraus.
MfG
Christian S. - Mi 19.12.07 10:42
Hallo!
Ein mehrzeiliger String ist ja auch nur
ein String! Was MultiLine und SingleLine sind, steht ja in der Hilfe sehr gut erklärt. Für Dich wäre IMHO SingleLine das richtige, weil Du ja die Zeilen eigentlich wie eine einzige Zeile behandeln willst.
Den Regex würde ich irgendwie so machen (Pseudo-Regex, da nur im Browser geschrieben ;-))
Quelltext
1:
| MSDV[ ]011070[ ]30[ ]01[ ]([^\n]+)\n MSDV[ ]011070[ ]30[ ]02[ ]([^\n]+) |
Der gesuchte String ist dann Match Nr.1 und Match Nr.2.
Grüße
Christian
bergrath - Mi 19.12.07 11:16
Hi Christian.
Erstmal danke für deine Antwort. Das würde in diesem Fall wohl funktionieren, aber der Text, den ich nach diesem Ausdruck durchsuchen will, ist viel länger und die Zahlen vorne, also MSDV 11112222333444 usw., ändern sich. Deswegen würde diese Variante wohl nicht funktionieren. Wobei die Zahle vorne, die nicht berücksichtigt werden sollen immer eine bestimmt Länge haben.
Welche Möglichkeiten gibt es sonst noch um einen Ausdruck zu finden, der über 2 Zeilen geht und dazwischen eine bestimmte Anzahl von Stellen auszulassen???
Ich müsste im Pattern formulieren, dass in der nächsten Zeile gesucht wird, wenn in der Zeile darüber ein Ausdruck mit SWAA - SWBB - SWCC beginnt ohne dass jedoch in der Zeile darüber ein "=" steht.
Das Problem, das dann entsteht ist leider, dass der Beginn der darunter liegenden Zeile sich immer ändert und nur ab einer bestimmten Position weitergelesen werden darf. Lässt sich soetwas mit Regex-Pattern überhaupt formulieren?
Vielen Dank im Voraus für die Tipps und Hinweise.
MfG
Christian S. - Mi 19.12.07 11:19
Kannst Du da vielleicht ein paar Beispiel-Stellen posten? Dann guck ich mir das heute nachmittag mal an, jetzt muss ich erstmal weg ;)
bergrath - Mi 19.12.07 11:43
Hi.
Danke dir.Ich hab einfach mal die ganze Textdatei angehängt.Keine Angst es ist nicht die ganze Textdatei, sondern nur ungefähr das erste Viertel davon ( Bis zu der Überschrift SFI, die mit Sternchen umrandet ist.
Ich muss da alle Ausdrücke rausfiltern, wie z.B. 23D=SWAA oder SWAA-SWAB = SWAC oder 23D*SWAD = SWAV oder SWAA-SWAB*SWAC = SWAD oder SWAA*SWC8*SWG=SWKL usw.
Das bekomme ich auch alles hin, außer bei solchen Ausdrücken, die über 2 Zeilen gehen. Das sind zwar nicht viele, aber der Vollständigkeit wegen benötige ich die auch. Es ist mir leider momentan ein Rätsel wie ich das realisieren soll.
Vielen Dank für Tipps und Hinweise im Voraus.
MfG
Christian S. - Mi 19.12.07 15:24
Wenn ich das richtig verstanden habe, könnte das hier helfen:
Quelltext
1:
| (?<lineNr>MSDV[ ][\d]{6}[ ](?:30|CC)[ ])01[ ](?:([^\=\$\n]+)(?:\n\k<lineNr>02))?([^\$\n]+\$) |
Bei diesem Input:
Quelltext
1: 2:
| MSDV 011070 30 01 23D-SWKM-SWKN-SWKO-SWKP-SWKQ-SWKR-SWKS-SWKT-SWKU-SWD6-SWD5-SWD4-SW MSDV 011070 30 02 D3-SWD2-SWD1-SWCB-SWC9-SWC8-SWC7-SWC6-SWC5=SWKV$ |
Gibt es als Ergebnis:
Quelltext
1: 2: 3:
| 1: [23D-SWKM-SWKN-SWKO-SWKP-SWKQ-SWKR-SWKS-SWKT-SWKU-SWD6-SWD5-SWD4-SW] 2: [ D3-SWD2-SWD1-SWCB-SWC9-SWC8-SWC7-SWC6-SWC5=SWKV$] lineNr: MSDV 011070 30 |
Hier musst Du also nur noch Submatch 1 und 2 zusammen kleben.
Einzeiliger Input:
Quelltext
1:
| MSDV 010550 30 01 SWKH*SWKF=SWKJ$ |
Gibt als Ergebnis:
Quelltext
1: 2: 3:
| 1: 2: [SWKH*SWKF=SWKJ$] linenr: MSDV 010550 30 |
Hier also nur Submatch 2 nehmen (1 ist ja leer).
Hilft das schonmal weiter?
bergrath - Mi 09.01.08 15:28
Hi.
Erstmal vielen Dank für die ausführliche Antwort, welche mir leider während meines Urlaubs entfallen ist. Inzwischen hat sich die Ausgangssituation ein wenig geändert.
Ich muss mittlerweile einen Match erhalten für folgenden zweizeiligen Ausdruck:
23D-SWKM-SWKN-SWKO-SWKP-SWKQ-SWKR-SWKS-SWKT-SWKU-SWD6-SWD5-SWD4-SW
D3-SWD2-SWD1-SWCB-SWC9-SWC8-SWC7-SWC6-SWC5=SWKV$
Es steht also nichts mehr vor dem Beginn der zweiten Zeile, so dass die Regex nun anders formuliert werden müsste.
Wie läßt sich das am besten realisieren, dass ein Ausdruck in dieser Art gefunden werden kann. Ich zerbreche mir schon seit 2 Tagen den Kopf darüber, aber ich komme zu keinem Ergebnis.
Vielleicht kann mir jemand von euch einen Hinweis oder Tip geben. Ich wäre dafür sehr dankbar.
MfG
Christian S. - Mi 09.01.08 15:36
Mein obiger Ausdruck sollte sich eigentlich ziemlich leicht darauf anpassen lassen.
bergrath - Mi 09.01.08 15:45
Hi Christian.
Ja, das glaube ich dir, aber wenn ich ehrlich bin, verstehe ich bei deinem Ausdruck fast nur Bahnhof.
Ich bin nicht gerade der Regex-Spezialist. Meine Regexes sehen alle ungefähr so aus.
[2-8][0-9]([ ]*|[A-Z0-9]*)([*][2-8A-Z][0-9A-Z]{3})*[*+-]*([2-8][A-Z0-9]{3})*([+-]*[S][W][A-Z0-9]{2})*[*]*([S][A-Z0-9]{3}[*]*([2-8][0-9][A-Z0-9]))*[=][S][A-Z0-9]{3}([$]?)
Mit dieser Regex finde ich z.B. Ausdrücke in dieser Art:
23D-SWCU-SWCT-SWA5=SWA2
23D-SWJN-SWJO-SWJP-SWJQ-SWJR-SWJS=SWJT
Wie könnte ich diese oben gepostete Regex erweitern, daß auch 2zeilige Matches dabei rauskommen. Danke im Voraus für Tips oder Hinweise.
MfG
bakachan - Mi 09.01.08 16:35
wie wärs mit an der entsprechenden Stelle ein \n ins regex einbaun?
Christian S. - Mi 09.01.08 21:50
Hallo, bergrath!
Eigentlich denke ich, dass es Deine Aufgabe ist, Dich so mit den Tipps, die man Dir gibt, zu beschäftigen, dass Du sie nachvollziehen kannst. Und dann sollte es Dir auch möglich sein, den RegEx von oben so anzupassen, dass er auf die neue Aufgabenstellung passt.
Aber okay, hier ein neuer RegEx, der dem obigen doch erstaunlich ähnlich sieht, wenn man nur ein paar Dinge herausstreicht ;-)
Quelltext
1:
| (?:([^\=\$\n]+)\n)?([^\$\n]+\$?) |
Im Anhang ein Screenshot vom Regulator, der zeigt, dass der RegEx alles matcht, was Du willst :-)
bergrath - Do 10.01.08 11:59
Hi Christian.
Vielen Dank für deine Antwort und dein Verständnis für meine Unwissenheit :wink:
Ich habe dein Regex-Pattern ausprobiert, aber leider bekomme ich damit den ganzen Text gematcht. Ich hätte aber gerne ein Regex, das nur 2 zeilige Ausdrücke matcht.Für alle anderen Ausdrücke, die ich filtern muss, habe ich die Regexes schon. Mir fehlt nur noch ein Regex für die zweizeiligen Ausdrücke.
Ich musste die Regex aber auch umschreiben, weil der Compiler zuerst meckerte über nicht erkannte Escapesequenzen. Ich habe die Regex nun folgendermaßen abgeändert:
("(?:([^\\=\\$\n]+)\n)?([^\\$\n]+\\$?)")
Wie ich schon erwähnte wird nun aber der ganze Text gematcht. Liegt das daran, daß ich die Escapesequenzen verdoppelt habe ( also aus einem "\" ein "\\" gemacht habe) oder wo liegt der Fehler?
Vielen Dank für Tips und Hinweise im Voraus.
MfG
Moderiert von
Christian S.: Code-Tags hinzugefügt
Christian S. - Do 10.01.08 13:00
Hallo!
Es hätte gereicht, ein @ vor den String zu schreiben, damit C# die Escape-Sequenzen ignoriert. Ich würde das dringend empfehlen, weil es viel übersichtlicher ist. Ich bin mir auch nicht sicher, ob Du jetzt überall genug Backslashes eingefügt hast ;-)
Wenn Du nur zweizeilige Ausdrücke matchen willst, darf der erste Teil des RegEx halt nicht optional sein, das sollte schon reichen.
Grüße
Christian
bergrath - Do 10.01.08 14:25
hi.
danke für den Hinweis. Ich habe jetzt alles mögliche probiert, aber ich erhalte immer den ganzen Text gematcht.
Quelltext
1:
| (@"(?:([^\=\$\n]+)\n)([^\$\n]+\$?)") |
Wie du siehst, habe ich die erste Klammer nicht mehr optional gemacht, aber als Match erhalte ich den ganzen Text.Aber immerhin habe ich dank deiner Hilfe schon den Fortschritt gemacht, daß der zweizeilige Match bei den Ergebnissen dabei ist.
Aber wie bekomme ich die anderen Matches weg, so daß nur die 2zeiligen Matches übrig bleiben?
Wäre sehr dankbar für zündende Ideen.
MfG
Moderiert von
Christian S.: Code-Tags hinzugefügt
bergrath - Fr 11.01.08 08:35
Hi.
Hat denn niemand einen Vorschlag wie man die Regex ändern kann, um nur 2zeilige Ausdrücke zu erhalten???
Viel Änderungen werden wohl nicht benötigt oder sehe ich das falsch???
Der erste Teil der Regex ist jetzt ja nicht mehr optional, aber wieso wird trotzdem alles gefunden. Ich blick nicht durch woran es hängt.
Hat jemand Tips oder Hinweise, die mir weiterhelfen könnten???
Vielen Dank im Voraus.
MfG
Christian S. - Fr 11.01.08 11:27
bergrath hat folgendes geschrieben: |
Viel Änderungen werden wohl nicht benötigt oder sehe ich das falsch??? |
Wenn Du siehst, dass es nicht viele sind, dann mach es doch selber :evil: Aber das Höchstmaß an Eigeninitiative scheint ja das Entfernen eines einzelnen Fragezeichens aus einem RegEx zu sein.
Wenn Du das Ganze mal im Regulator anguckst, dann wirst Du sehen, dass nicht alles gematcht wird, sondern von den einzeiligen Ausdrücken nur ein Teil bis zu einem bestimmten Zeichen. Und dann ist auch klar, was Du machen musst.
bergrath - Fr 11.01.08 11:59
Nein, das ist nicht das Höchstmaß an Eigeninitiative. Ich habe viele andere Varianten probiert, die aber alle nicht funktioniert haben. Ich habe ja auch erwähnt, daß ich die Regexen, die ich habe anders geschrieben habe und deswegen diese Schreibweise nur schwer nachvollziehen kann.
Ich benutze zum Testen für die Regexen den "Regex-Designer". Ist der Regulator besser oder hat der mehr Funktionen? Wenn ja, dann werd ich den mal nutzen zum Testen.
Und ich verstehe nicht wieso ich hier doch recht barsch angegangen werde nur weil ich Fragen stelle, wozu solche Foren ja letztendlich auch gedacht sind. Bin halt noch neu auf diesem Gebiet und werde mir das passende Verhalten im Board schon noch aneignen.
Naja dann bedanke ich mich mal wieder recht herzlich und hoffe auf dein Verständnis für meine Unwissenheit. Es ist immerhin noch kein Meister vom Himmel gefallen.
MfG
Christian S. - Fr 11.01.08 12:10
Die Antwort, in der ich die Dir unbekannte Syntax benutzt habe, stammt vom 19.12.2007! Das sollte doch wohl genug Zeit sein, sich mit dieser Syntax zu beschäftigen. Das meine ich mit Eigeninitiative. Es sieht für mich so aus, als würdest Du den Regex nehmen und wenn Du ihn nicht verstehst, versucht nicht, durch eigenständiges Lernen das zu ändern.
Foren sind dazu da, Fragen zu stellen, das ist richtig. Aber es wird auch erwartet, dass Du Dich mit den Antworten beschäftigst und sie nicht einfach ungesehen übernimmst, ohne zu versuchen, sie zu verstehen. Und ich habe von Dir z.B. noch keine Frage gesehen, die darauf hinauslief, "meinen" Regex zu verstehen.
bergrath - Fr 11.01.08 12:56
Ich habe mich schon damit beschäftigt und werde jetzt mal kurz sagen wie sich diese Regex für mich anhört:
Quelltext
1:
| (@"(?:([^\=\$\n]+)\n)?([^\$\n]+\$?)") |
(?: bedeutet am Anfang
([^\= bedeutet kein Gleichheitszeichen
\$ bedeutet Zeilenende
\n] bedeutet Zeilenumbruch???
+) bedeutet mindestens einmal oder mehrmals
\n)? bedeutet dass es optional ist
wie sich dies nun zu einem sinnvollen Satz zusammenbauen lässt kann ich dir nicht sagen. Evtl. so:
Am Anfang des Ausdrucks darf kein Gleichheitszeichen stehen und am Zeilenende kommt ein Umbruch mindestens einmal. Der ganze Ausdruck ist optional, aber darüber haben wir ja schon gesprochen, dass zum matchen der zweizeiligen Ausdrücke aus diesem optionalen Zeichen eher ein * gemacht werden sollte.
Das ist die Weise in der ich diesen Ausdruck verstehe, aber die ist wohl ziemlich daneben schätze ich mal. Für Korrekturen meiner Aussage wäre ich dir dankbar.
MfG
Moderiert von
Christian S.: Code-Tags hinzugefügt
Christian S. - Fr 11.01.08 13:07
Hm, nee, da geht noch ein bisschen was durcheinander. Mal von innen nach außen:
Teil 1:
Quelltext
1: 2: 3: 4: 5: 6:
| (?: Teilausdruck bekommt keine eigene Nummer ( [^\=\$\n]+ Kein Gleichheitszeichen / Dollarzeichen / Zeilenumbruch, "+" = ein oder mehrmals ) \n ein Zeilenumbruch ) |
Teil 2:
Quelltext
1: 2: 3: 4:
| ( [^\$\n]+ Kein Dollarzeichen / Zeilenumbruch, Gleichheitszeichen erlaubt, "+" = ein oder mehrmals \$? optional ein Dollarzeichen am Ende ) |
Ein gutes Tutorial zu regulären Ausdrücken:
http://tut.php-quake.net/regex.html
bergrath - Fr 11.01.08 13:56
Hmm. Dann mal danke. Ich werde mich jetzt nochmal damit beschäftigen und versuchen dahinter zu steigen.
Noch eine Frage zum Regulator: Unterscheidet der sich gravierend vom Regex-Designer???
Dann würde ich nämlich den mal testen, falls es da große Unterschiede gibt.
MfG
Christian S. - Fr 11.01.08 15:04
Regex-Designer habe ich noch nicht ausprobiert, der Regulator ist recht einfach gehalten, mir reicht er. :nixweiss:
bergrath - Mo 14.01.08 10:50
Hi.
also mittlerweile bin ich ein wenig vorangekommen. Hier ist mein Regex, das aber leider immer noch nicht so richtig funktioniert. Aber es kann eigentlich nur noch an einer Kleinigkeit hängen.
[+-]*([S][A-Z][A-Z0-9][A-Z0-9]|[2-8][0-9][ 0-9A-Z])([*+-][S][A-Z][A-Z0-9][A-Z0-9]|[2-8][0-9][A-Z ]*)*[^=\n\$]^(^\=)[.][=][S][A-Z][A-Z0-9][A-Z0-9][$]
Ich möchte nun zu den einzelnen Teilen ein bisschen was erklären, damit mir vielleicht jemand erklären kann wo mein Fehler liegt
Teil 1:
[+-]*([S][A-Z][A-Z0-9][A-Z0-9]|[2-8][0-9][ 0-9A-Z])([*+-][S][A-Z][A-Z0-9][A-Z0-9]|[2-8][0-9][A-Z ]*)* dies sind die Ausdrücke, die in der ersten Zeile stehen wobei ich mir nicht sicher bin, ob das einen Treffer ergibt, weil der Ausdruck ja in der Mitte getrennt wird und statt SWD3 nur SW da steht und das D3 in der zweiten Zeile steht.
[^=\n\$] soll bedeuten, dass kein = oder ein Zeilenumbruch oder ein Dollarzeichen in der ersten Zeile stehen soll
^(^\=)[.][=] am Zeilenanfang kein = und dann alles lesen bis zum =
[S][A-Z][A-Z0-9][A-Z0-9][$] dann alle Ausdrücke, die mit einem Dollarzeichen enden.
Ich hoffe das hilft zum Verständnis des Problems und jemand kann mir sagen wo der Fehler liegt.
Vielen Dank im Voraus.
MfG
bergrath - Mo 14.01.08 15:20
Hi.
Weil mir auf meinen letzten Beitrag niemand antwortet stelle ich hier mal eine andere Frage in den Raum.
Und zwar würde ich gerne wissen wie ich folgenden Ausdruck finden könnte:
Der Ausdruck beginnt mit SWAA . Danach soll die ganze Zeile gelesen werden, aber es soll kein = in der Zeile stehen.Am Ende der Zeile ist ein Zeilenumbruch. In der nächsten Zeile soll dann gelesen werden bis zu einem Dollarzeichen.
Ich wollte das so machen: [SWAA][\.]*[^\=][\n]+[.]*[=][.]*[$]$
Das funktioniert aber leider auch nicht so, wie ich mir das vorgestellt habe, aber ist bestimmt leichter zu formulieren.
Es darf in der Zeile einfach kein = stehen, die Zeile muss mit SWAA beginnen, es muss ein Zeilenumbruch enthalten sein und in der darauf folgenden Zeile muss bis zum $-Zeichen gelesen werden. Hört sich ja nicht so schwer an, aber ich bekomms einfach nicht hin.
Ich nehm mir so langsam echt die Lebensfreude wegen diesen Regexes.
Vielleicht kann mir ja jemand weiterhelfen. Danke im Voraus.
MfG
Christian S. - Mo 14.01.08 15:33
bergrath hat folgendes geschrieben: |
Weil mir auf meinen letzten Beitrag niemand antwortet |
Ja, schon unverschämt, dass die Leute die hier freiwillig helfen nicht vorm Rechner sitzen und drauf warten, dass Du 'ne Frage stellst. 5h Wartezeit sind wirklich fürchterlich :roll:
Du schreibst auch nur, dass die RegEx nicht funktionieren, aber das ist ja nun keine wirklich genaue Beschreibung. Deine Monster-Regex (Was spricht gegen den Regex, den ich vorgeschlagen habe?) nach einem Fehler abzusuchen würde es einfacher machen, wenn Du sagst, was die Regex falsch matchen.
bakachan - Mo 14.01.08 15:38
also ich weiss nicht was du dir bei deinem Regex gedacht hast aber
auf deinen Regex: [SWAA][\.]*[^\=][\n]+[.]*[=][.]*[$]$
kann nichts matchen.
1. du willst eine Zeichenfolge "SWAA" mit deinem Regex [SWAA] kriegst du ein Zeichen das entweder S oder W oder A ist
2. [\.]* damit findest du eine beliebig lange zeichenfolge die nur aus Punkten besteht
3. wozu eigentlich [\n] ? es ist ne auswahl für eine möglichkeit??? lass die eckigen klammern da weg
4. dein + nach dem [\n] wozu is das da? ich dachte du wolltest extra ausdrücke die mit SWAA anfangen udn über 2 zeilen gehen usw .. das + macht den ersten teil optional wenn ich mich richtig erinnere
5. [$]$ in einem Regex steht $ für das Ende der Zeichenkette und kann somit nicht 2 mal hintereinander auftreten wenn du das richtige $ matchen willst musst du es escapen
meine Empfehlung:
Wenn du mit Regex arbeiten willst erkundige dich erstmal über die Grundlagen von Regex.
Die formulierung deines Ausdrucks verrät mir das du diese nichtmal ansatzweise beherscht.
Kha - Mo 14.01.08 15:41
Zum neuen Regex: Trifft wohl noch nicht alle deine Voraussetzungen (soll am Anfang nun "SWAA", "SWAA ." oder "SWAA." gematcht werden?), aber schau's dir einfach mal an:
Quelltext
1:
| (?<line1>SWAA[^=\n]*)\n(?<line2>[^$]*\$) |
Testinput:
C#-Quelltext
1: 2:
| SWAAjeinf ieönfld dkjflköjefe$dfefdgdf |
bergrath - Mo 14.01.08 16:24
Hi.
@ Christian S.
Ich wollte nicht sagen, daß es unverschämt von irgendjemanden ist mir nicht zu antworten.
Ich habe mir nur einen Ansatz überlegt wie ich es noch lösen könnte. Und wenn ich sage, daß die Regex nicht funktioniert, so ist es meistens so daß garnichts gematched wird.
Gegen dein Regex spricht, daß damit auch sehr viel Erklärungen, die im Text stehen gematched werden. Und ich brauche nur die Ausdrücke wie SWAA-SWAB=SWAC(und am besten längere Ausdrücke, die über 2 Zeilen gehen). Mit deinem Regex wird leider noch sehr viel mehr getroffen. Ich habe probiert mit deinem Regex zu arbeiten und auf meine Vorstellungen anzupassen. Da das sehr lange nicht geklappt hat, bin ich wieder zu meinem Ansatz übergegangen.
Trotzdem nochmal danke.
@bakachan:
Danke dass du mir meine Fehler aufgezeigt hast. Ich habe die Regexes vorher immer von Hand zu Fuss zusammengebaut und weniger mit Sonderzeichen gearbeitet und mir unterlaufen deswegen wohl solche Fehler, obwohl ich mittlerweile schon mehrere Tutorials gelesen habe. Aber ich werde versuchen mich zu bessern.
@khabarakh:
Danke für deinen Vorschlag! Ich muss jetzt leider aufhören zu arbeiten, aber ich werde mich später zuhause damit beschäftigen und dann berichten, ob es funktioniert hat oder es noch etwas auf meine Bedürfnisse versuchen abzuändern.
Vielen Dank Jungs und verzeiht mir meine Unwissenheit.
MfG
Kha - Mo 14.01.08 20:05
@bakachan: Oh, hab deinen Beitrag erst jetzt gesehen. Zwei kleine Verbesserungen, damit sie sich unser Lernender nicht falsch einprägt ;) :
bakachan hat folgendes geschrieben: |
das + macht den ersten teil optional wenn ich mich richtig erinnere |
+ ist "mindestens einmal"
bakachan hat folgendes geschrieben: |
in einem Regex steht $ für das Ende der Zeichenkette und kann somit nicht 2 mal hintereinander auftreten wenn du das richtige $ matchen willst musst du es escapen |
1. $ matcht mit der Multiline-Option (die wohl benutzt wird) auch das Zeilenende.
2. $ ist wie auch der Punkt innerhalb von Klassen quasi bereits escapt, also "[$]$" = "\$$".
bakachan - Di 15.01.08 09:12
ok hatte mich also in diesen 2 Dingen bissel geirrt sorry
bergrath - Di 15.01.08 11:15
Hi Leute.
Danke für eure Hilfe.
Mit dem Regex von Khabarakh erhalte ich folgende Ausgabe. Ich habe die Regex vorher noch so abgeändert, daß alle (***)und somit die Teilebezeichnungen rausgefiltert werden. Die Regex sieht nun so aus:
(@"((([^\=\$\n\(***)]+)\n)([^\$\n]+\$))")
Als Ausgabe erhalte ich in meiner Textbox Folgendes ( nur ein kleines Beispiel):
IECAB +SWKU
23 =SWKU$ gefunden an Position: 53445
23D-SWKM-SWKN-SWKO-SWKP-SWKQ-SWKR-SWKS-SWKT-SWKU-SWD6-SWD5-SWD4-SW
D3-SWD2-SWD1-SWCB-SWC9-SWC8-SWC7-SWC6-SWC5=SWKV$ gefunden an Position: 53551
IECEF IECFF +SWKW
SWCB*SWD6=SWKW$ gefunden an Position: 53672
IECEE IECFE +SWKX
Ich möchte die Matches, die über 2 Zeile gehen allerdings lieber in einer Zeile stehen haben. Über den Ausdrücken, die ich rausfiltere(z.B. SWCB*SWD6=SWKW$), steht in der Zeile obendrüber nämlich immer, ob es ein + oder - Feature ist (z.B. +SWKW) und der korrespondierende Code aus einer anderen Datenbank,den ich benötige(hier im Bsp.: IECEF IECFF).
Dadurch, daß die 2zeilige Regex 2 Zeilen belegt, fehlt mir hier also die normal darüber stehende Zeile mit den Informationen, ob es ein "+" oder "-"-Feature ist und der korrespondierende Code aus der anderen Datenbank.
Ich habe versucht das Pattern zusammenzufügen und aus den 2 Teilen des Regex einen Ausdruck zu formen und habe dafür nochmal eine Klammer um den ganzen Ausdruck gesetzt.
Leider erhalte ich dann als Ergebnis nicht eine einzeiligen Ausdruck. Aber da ich mir die Ergebnisse in einer Textbox anzeigen lasse, die sehr breit ist, müsste es möglich sein den 2zeiligen Regex in einer Zeile anzeigen zu lassen und dadurch auch die darüber liegende Zeile mit den anderen Informationen zu erhalten.
Die Frage ist nur wie??? Könnt ihr mir vielleicht Tips oder Hinweise dazu geben???
Vielen Dank im Voraus.
MfG
bergrath - Mi 16.01.08 09:07
Hi.
Also mittlerweile habe ich mir überlegt wie ich trotz der fehlenden Zusatzinformationen weiter vorankommen kann, indem ich sie per Funktion im Text suche.
Ich verwende folgende Regex, um die Ausdrücke zu filtern:
C#-Quelltext
1:
| Regex r23 = new Regex(@"((([^\=\$\n\(***)]+)\n+([^\$\n]+\$)))",RegexOptions.Multiline); |
Leider ist jetzt ein neues Problem entstanden. Der folgende Ausdruck wird nicht richtig gematcht.
(45,1*4*5*6*7*8*A*B*C*E*I*G*H*F*M*K*S*Q*Y)*(65,3*4*6*7*8*9*A*B*C*D
*E*F*U*V*W*X*Y*Z)=SWLO$
Als Ergebnis erhalte ich folgendes:
D
*E*F*U*V*W*X*Y*Z)=SWLO$ gefunden an Position: 56440
Die obere Zeile wird vor dem D abgeschnitten. Aber ich verstehe nicht warum. Kann mir jemand verraten, woran das liegt?
Der andere 2zeilige Ausdruck, der im Text enthalten ist, wird ja auch nicht vor dem letzten Buchstaben abgeschnitten.
23D-SWKM-SWKN-SWKO-SWKP-SWKQ-SWKR-SWKS-SWKT-SWKU-SWD6-SWD5-SWD4-SW
D3-SWD2-SWD1-SWCB-SWC9-SWC8-SWC7-SWC6-SWC5=SWKV$ gefunden an Position: 53551
Welcher Teil meiner RegEx ist dafür verantwortlich, daß dies so passiert.
Wäre echt dankbar, wenn mir jemand meinen Fehler aufzeigen könnte. Vielen Dank schonmal im Voraus.
MfG
bakachan - Mi 16.01.08 09:14
"[^\=\$\n\(***)]"
darin hast du doch selbst angegeben das keine Klammern und Sterne in der ersten Zeile sein dürfen bzw diese nicht mitgematcht werden
Edit: "***" was soll das eigentlich bringen ? so wie ich das sehe hast du 3 mal den stern als auswahl in den eckigen klammern gestellt oder hat das ne Bedeutung die ich noch nciht kenne?
bergrath - Mi 16.01.08 13:19
Hi.
Durch die *** Filtere ich Bezeichnungen raus, die zwischen 3 Sternen stehen ( das sind Teilebezeichnungen, die ich nicht benötige).
Aber ich habe mir das so gedacht, dass dies nur gilt wenn 3 Sterne aufeinander folgen. Oder habe ich da einen Denkfehler gemacht?
Funktionieren tut das auf alle Fälle mal mit den (***). Ist dieser Ausdruck dann auch dafür verantwortlich, dass das alles abgeschnitten wird in dem Ausdruck?
Regex r23 = new Regex(@"((([^\=\$\n]+)\n)([^\$\n]+\$))",RegexOptions.Multiline);
Habe es jetzt wieder geändert und erhalte die richtigen Matches. Allerdings stehen jetzt wieder die Teilebezeichnungen dabei. Diese stehen immer zwischen jeweils ***.
*** EXCEPT EUROPEAN PRINCIPLE TERR *** XAE02 +SWNO
Diesen Ausdruck zwischen den *** und die *** vornedran und hintendran möchte ich auch wegbekommen. Aber wie?
Wäre sehr dankbar für hilfreiche Tips.
MfG
bakachan - Mi 16.01.08 14:08
du könntest die ***Text*** in ne extra gruppe packen allerdings würde das nicht verhindern das sie mit gematcht werden (lässt sich auch nicht verhindern weil sie ja teil des matches sein können) sondern höchstens das sie in ne eigne gruppe gepackt werden
was du allerdings tun könntest wäre vorher per Regex.Replace mit dem Regex
\*{3}.*\*{3}
diese texteile durch nichts ersetzen -> sie wären aus dem string raus
bergrath - Mi 16.01.08 16:22
Hi bakachan.
Vielen Dank für die Regex. Hat einwandfrei funktioniert. Habe jetzt dank deiner Hilfe so ziemlich alle Ausdrücke,die ich brauche, zusammen.
Hier mal die Regexen, die den Text so wie gewollt kürzen:
C#-Quelltext
1: 2: 3: 4: 5: 6:
| textBox1.Text = new Regex("(?<=^|\n).{18}").Replace(gekürzteSolve, ""); gekürzteSolve = textBox1.Text; textBox1.Text = new Regex(@"\*{3}.*\*{3} ").Replace(gekürzteSolve, ""); gekürzteSolve = textBox1.Text; Regex r23 = new Regex(@"(((^[^***][^\=\$\n]+)\n)([^\$\n]+\$))", RegexOptions.Multiline); |
Ausgabe:( nur ein kleiner Auszug davon)
23 =SWKT$ gefunden an Position: 38913
IECAB +SWKU
23 =SWKU$ gefunden an Position: 38951
23D-SWKM-SWKN-SWKO-SWKP-SWKQ-SWKR-SWKS-SWKT-SWKU-SWD6-SWD5-SWD4-SW
D3-SWD2-SWD1-SWCB-SWC9-SWC8-SWC7-SWC6-SWC5=SWKV$ gefunden an Position: 39016
IECCA IECCB IECCC IECCD I
SWKR*SWKQ*SWKP*SWKO*SWKN*SWKM=SWKD$ gefunden an Position: 40103
IEMAD +SWLF
23 =SWLF$ gefunden an Position: 40337
Aber ein letzte kleine Frage hätte ich noch und hoffe, daß mir vielleicht auch noch hier jemand einen Hinweis geben könnte woran es liegt.
Wenn ich die Regex r23 alleine laufen lasse, also ohne die 2te-Replace-Regex(also die, die die Sternchen und den dazwischen stehenden Text entfernt), dann erhalte ich fast das, was ich die ganze Zeit gesucht habe, nämlich nur die 2zeiligen Ausdrücke. Das Ganze hat allerdings einen kleinen Schönheitsfehler. Denn es wird noch etwas ausgegeben was nicht gewollt ist. Hier schreibe ich mal den Code und danach poste ich noch die Ausgabe. Vielleicht kann mir jemand erklären woran das liegt. Ich wäre dafür sehr dankbar und verspreche euch so schnell nicht mehr mit Regexen zu belästigen.
Hier der Code:
C#-Quelltext
1: 2: 3:
| textBox1.Text = new Regex("(?<=^|\n).{18}").Replace(gekürzteSolve, ""); gekürzteSolve = textBox1.Text; Regex r23 = new Regex(@"(((^[^***][^\=\$\n]+)\n)([^\$\n]+\$))", RegexOptions.Multiline); |
Wenn ich das kompiliere, erhalte ich folgende Ausgabe:
CBV SOLVE TABLE 0098 26 OCT 07
23D+24R$ gefunden an Position: 136
23D-SWKM-SWKN-SWKO-SWKP-SWKQ-SWKR-SWKS-SWKT-SWKU-SWD6-SWD5-SWD4-SW
D3-SWD2-SWD1-SWCB-SWC9-SWC8-SWC7-SWC6-SWC5=SWKV$ gefunden an Position: 53551
(45,1*4*5*6*7*8*A*B*C*E*I*G*H*F*M*K*S*Q*Y)*(65,3*4*6*7*8*9*A*B*C*D
*E*F*U*V*W*X*Y*Z)=SWLO$ gefunden an Position: 56375
Das ist genau das was ich von Anfang an als Ergebnis erhalten wollte. Leider sind die ersten beiden Zeilen zuviel und sollten nicht ins Ergebnis mit einfliessen.
Wenn ich das richtig sehe, werden die ersten beiden Zeilen der Ausgabe auch als ein Match gesehen, weil hinter dem 24R noch ein Dollarzeichen steht.
Ich müsste der Regex nur mitteilen, daß in der zweiten Zeile des Matches ein = stehen muss. Dann würden die ersten beiden Zeilen nicht mehr gematcht. Nur bekomme ich das leider nicht hin. Ich habe schon überall ein = in der zweiten Klammer hingemacht, aber es funzt nicht. Kann mir vielleicht jemand verraten, wie ich dieses kleine Problem lösen könnte??? Ich wäre dafür sehr dankbar.
MfG
bakachan - Mi 16.01.08 16:45
1. das = in ner eckigen klammer zusammen mit anderen auswahlmöglichkeiten legt ja nicht fest das unbedingt ein = vorkommen muss es ist ja nur eine auswahlmöglichkeit
wenn du willst das unbedingt ein = drinne ist darfst du es nicht in [] zusammen mit anderen zeichen schreiben sondern musst es einfach so hinschreiben
2. wieso hast du immernoch [^***] drinne? ich hab doch schon mehrmals erklärt das das nutzlos ist es sagt nur das das erste (nicht die ersten drei da es ja nur auswahlmöglichkeiten sind) Zeichen kein stern sein darf und außerdem die ausdrücke mit den ***Text*** hast du doch schon ausgefiltert bzw wenn du unbedingt willst das am Anfang keine 3 sterne stehen musst du es so schreiben : ^\*^\*^\* oder [^*]{3}
bergrath - Mi 16.01.08 19:54
hi.
Ich weiß nicht sicher woran es liegt, aber sobald ich [^***] weglasse wird viel mehr gematcht und nicht nur die 2zeiligen Ausdrücke.
Ich habe jetzt an jeder Stelle in der 2ten Klammer ein = gesetzt, aber es funktioniert nicht. Ich habe es probiert mit (\=)+ oder (\=\)+ oder[=]+ oder
(\=\)+\ oder [=]+ - an jeder Stelle habe ich die einzelnen Versionen in die Klammer eingefügt, aber ohne Erfolg.Was mache ich falsch? Wie kann man das realisieren, dass die 2 ersten Zeilen nicht gematcht werden bzw. wo muss das = hin??? Ich bin echt langsam am verzweifeln. Könnte einen Hinweis gebrauchen, damit mir ein Licht aufgeht.
Regex r23 = new Regex(@"(((^[^***][^\=\$\n]+)\n)(([^\$\n]+\$)))", RegexOptions.Multiline);
Vielen Dank für Tips und Hinweise im Voraus.
Mfg
bakachan - Do 17.01.08 08:57
ich weiss ich wiederhole mich aber:
Zitat: |
1. das = in ner eckigen klammer zusammen mit anderen auswahlmöglichkeiten legt ja nicht fest das unbedingt ein = vorkommen muss es ist ja nur eine auswahlmöglichkeit
wenn du willst das unbedingt ein = drinne ist darfst du es nicht in [] zusammen mit anderen zeichen schreiben sondern musst es einfach so hinschreiben |
genau das hab ich dir in der vorherigen antwort auch geschrieben nur du scheinst es nicht richtig gelesen zu haben
bergrath - Do 17.01.08 13:20
Hi.
Ich habe das = überall hingeschrieben. Vor der Klammer,nach der Klammer. Hab echt jede Position probiert, aber ohne Erfolg.
Habe auch verschiedene Schreibweisen probiert. Aber es funktioniert nicht. Muss ich vielleicht den ganzen 2ten Teil der Regex umschreiben?
Ich bin echt planlos was ich noch probieren soll. Wenn das = nicht in die [] darf, bleiben ja nicht so viele Positionen übrig wo es hinkommen könnte.
Ich habe alles ausprobiert denke ich mal.
Wo muss das = denn hin? Kann ich es vielleicht doppelt negieren? Habe mir ein Regex-Buch besorgt, aber da finde ich nichts zur doppelten Negation.
Danke im Voraus für Tips und Hinweise.
MfG
bakachan - Do 17.01.08 14:03
ich hab mich jetz nich lange damit beschäftigt aber
wie wärs zum beispiel mit
([^\$\n]+=[^\$\n]+\$)
da is dein = mit drinn
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!