Laden...

Regex match "falsch"

Erstellt von Kalleberlin vor 15 Jahren Letzter Beitrag vor 15 Jahren 2.176 Views
K
Kalleberlin Themenstarter:in
165 Beiträge seit 2007
vor 15 Jahren
Regex match "falsch"

Hallo liebe Gemeinde 😃,

kleines Problem, große Ursache:

Mein String kann so:

"3 90"

oder aber z.b:

"14 55"

so aussehen.

Wenn ich nun als pattern "[0-9]" angebe, bekomme ich die 3, aber nicht die 14 (ist dann 1). Wenn ich "[0-9]*" angebe, bekomm ich die 14, aber auch 39. Wie kann ich das anstellen das ich beides richtig bekomme?

Bitte nicht wundern das ich dafür Regex verwende, der String ist an sich wesentlich komplexer, nur hier happerts irgendwie 😦.

Besten dank im vorraus,

Kalleberlin

PS: Ja ich hab das Regex-Tutorial hier im Forum schon gelesen, komme aber leider trotzdem nicht weiter...

If u want to finish first, u have to finish first.
1.378 Beiträge seit 2006
vor 15 Jahren

Also [0-9]+ liefert mir bei "3 90" im ersten Match 3 und im zweiten 90. Was stimmt daran also nicht?

Das * ist hier unpassend, da dadurch auch das Leerzeichen matcht.

Lg XXX

K
Kalleberlin Themenstarter:in
165 Beiträge seit 2007
vor 15 Jahren

Hallo xxxprod,

danke für die schnelle Antwort 😃.

ok, ich poste nun doch den ganzen String 😃.

Ein Beispiel wäre

"09/08/2008 16:58:06.61 00:00:00.49 R 0000_0000000164750397 A4 3 90"

Mein Pattern dazu:

    protected const string SearchPattern =  
        @"([0-99]{2}\/[0-99]{2}\/[0-9999]{4})" +   
        @"([0-99]{2}\:[0-99]{2}\:[0-99]{2}\.[0-99]{2})" +   
        @"([0-99]{2}\:[0-99]{2}\:[0-99]{2}\.[0-99]{2})" +  
        @"([A-Z])" +   
        @"([0-99]{4}_[0-99]{16})" +  
        @"([A-Z][0-9])" +   
        @"([0-9]+)" +  //Hier happerts  
        @"([0-9]+)";  

Bei dem beispiel oben, hab ich 39 anstatt 3.

If u want to finish first, u have to finish first.
1.378 Beiträge seit 2006
vor 15 Jahren

Abgesehen davon, dass dir ein paar Abstände gefehlt haben, passts soweit:

([0-99]{2}\/[0-99]{2}\/[0-9999]{4}) ([0-99]{2}\:[0-99]{2}\:[0-99]{2}\.[0-99]{2}) ([0-99]{2}\:[0-99]{2}\:[0-99]{2}\.[0-99]{2}) ([A-Z]) ([0-99]{4}_[0-99]{16}) ([A-Z][0-9]) ([0-9]+) ([0-9]+)

Lg XXX

K
Kalleberlin Themenstarter:in
165 Beiträge seit 2007
vor 15 Jahren

Hallo xxxprod,

ich sehe da jetzt gerade keine Änderung im vergleich zu meinem 🤔.

If u want to finish first, u have to finish first.
946 Beiträge seit 2008
vor 15 Jahren

Abgesehen davon, dass dir ein paar Abstände gefehlt haben, passts soweit:

Bei dir sind die einzelnen Teile mit ")(", bei ihm ") (" verbunden.
Man beachte das Leerzeichen.

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo Kalleberlin,

der Pattern [0-9]+ matcht bei dem Eingabestring "3 90" sicher nicht auf "39" weil ja "39" gar nicht enthalten ist.

Kennst du außer dem Tutorial auch den On-the-fly Regex-Tester: Regex-Lab?

Damit habe ich xxxprod Pattern gegen deinen String getestet und der Pattern tuts.

herbivore

K
Kalleberlin Themenstarter:in
165 Beiträge seit 2007
vor 15 Jahren

Hallo herbivore,

ohne dein Regex-Tester, hätte ich den suchpattern niemals so zustande bekommen 😄.

Und wegen 3 bzw 39, er matcht definitiv auf 39, sonst hätte ich mich nicht gemeldet 😉.

Ist es "falsch" das ich nur in die Gruppen schaue?

Kalleberlin
//edit:

In deinem Regex-lab, matcht es ja auch richtig 😕

If u want to finish first, u have to finish first.
49.485 Beiträge seit 2005
vor 15 Jahren

Hallo Kalleberlin,

Und wegen 3 bzw 39, er matcht definitiv auf 39, sonst hätte ich mich nicht gemeldet 😉.

zeig mir mal bitte genau den Pattern, von dem du meinst, dass er bei der Eingabe von "3 90" auf "39" matcht. Das geht schon vom Grundsatz nicht, da ein Pattern nur auf zusammenhängende Teile matcht. Und 3 und 9 hängen ja in "3 90" nicht zusammen. Wenn überhaupt kann es sein, dass ein Pattern auf "3 9" matcht, aber nicht auf "39".

herbivore

K
Kalleberlin Themenstarter:in
165 Beiträge seit 2007
vor 15 Jahren

Hallo herbivore,

ich habe den Sourcecode leider gerade nicht da (auf Arbeit). Ich Sende morgen mal ein Screenshot vom debugger.

Den Wert selber hole ich mir mittels int.Parse aus der der Gruppe[index].

Ich hatte mein pattern (am ende) vor dem Forums eintrag so:

@"([0-99]$)" + //Hier happerts
@"([0-99]
$)";

Ich denke mal das ich xxxprods pattern getestet habe, allerdings bin ich mir gerade ziemlich unsicher, da deine Aussagen so gut wie immer Hand und Fuss haben 😄.

Danke,

Kalleberlin

If u want to finish first, u have to finish first.
G
497 Beiträge seit 2006
vor 15 Jahren

@"([0-99]*$)" + //Hier happerts

tu dir selbst einen Gefallen und schau dir in aller Ruhe ein Tutorial zu regulären Ausdrücken an. Ich kann das hier als Einstieg empfehlen.

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo GarlandGreene,

tu dir selbst einen Gefallen und schau dir in aller Ruhe ein Tutorial zu regulären Ausdrücken an. Ich kann das hier als Einstieg empfehlen.

PS: Ja ich hab das Regex-Tutorial hier im Forum schon gelesen, komme aber leider trotzdem nicht weiter...

herbivore

K
Kalleberlin Themenstarter:in
165 Beiträge seit 2007
vor 15 Jahren

Guten Morgen 😃,

Mein aktuelles Pattern:


protected const string SearchPattern =
            @"([0-99]{2}\/[0-99]{2}\/[0-9999]{4})" + 
            @"([0-99]{2}\:[0-99]{2}\:[0-99]{2}\.[0-99]{2})" + 
            @"([0-99]{2}\:[0-99]{2}\:[0-99]{2}\.[0-99]{2})" + 
            @"([A-Z])" +
            @"([0-99]{4}_[0-99]{16})" + 
            @"([A-Z][0-9])" + 
            @"([0-9]+)" +
            @"([0-9]+)"

Mein aktueller String:


"09/08/2008 16:58:06.61 00:00:00.49 R 0000_0000000164750397 A4 3 90"

Mein aktueller debug im Anhang.

Gruß,
Kalleberlin

If u want to finish first, u have to finish first.
1.378 Beiträge seit 2006
vor 15 Jahren

Das selbe Problem wie gestern - du entfernst die leerzeichen aus dem Pattern wodurch es nicht mehr richtig ist.

So sollte dein zusammengebauter String aussehen:(ungetestet)


protected const string SearchPattern =
            @"([0-99]{2}\/[0-99]{2}\/[0-9999]{4}) " +
            @"([0-99]{2}\:[0-99]{2}\:[0-99]{2}\.[0-99]{2}) " +
            @"([0-99]{2}\:[0-99]{2}\:[0-99]{2}\.[0-99]{2}) " +
            @"([A-Z]) " +
            @"([0-99]{4}_[0-99]{16}) " +
            @"([A-Z][0-9]) " +
            @"([0-9]+) " +
            @"([0-9]+)"

Lg XXX

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo Kalleberlin,

war das die Antwort auf meine Frage? Ich nehme es mal an.

Interessieren tut ja nur der Teil "3 90" aus dem Input und der Teil @"([0-9]+)" + @"([0-9]+)" aus dem Pattern, was "([0-9]+)([0-9]+)" entspricht. Und wenn du das mal ausprobierst, bekommst du keinen Match von "39". Und wenn du, wie von xxxprod gesagt, das Leerzeichen einfügst, also "([0-9]+) ([0-9]+)" dann bekommst du genau was du willst also "3" in der ersten Gruppe und "90" in der zweiten. Ich sehe da immer noch nicht wo da auf "39" gematcht werden könnte.

herbivore

PS: Jetzt sehe ich im Debug, dass da tatsächlich "39" steht. Allerdings fehlen auch im Eingabe-String die Leerzeichen. Wo sind die hin? Die musst du ja zu irgendeinem Zeitpunkt entfernt haben. Und warum?

Wenn das Leerzeichen zwischen den letzten beiden Zahlen entfernt wird, und das beliebige Zahlen sein können, gibt es natürlich - weder mit Regex noch sonst wie - eine Chance zu erkennen, wo die eine Zahl aufhört und die andere anfängt.

Dann ist es ganz einfach so, dass die erste Gruppe auf so viel wie möglich matcht (hier also "39") und die zweite Gruppe auf den minimalen Rest ("0").

Aber nochmal: Das entspricht nicht der Ausgangssituation, die du oben geschildert hattest, in der im Input-String ein Leerzeichen zwischen den Zahlen steht.

K
Kalleberlin Themenstarter:in
165 Beiträge seit 2007
vor 15 Jahren

Hallo xxxprod,

wenn ich da jetzt Lerrzeichen rein setze, matcht gar nix mehr.

Ich habe den pattern ja auch mit dem Regex Tester getestet. Es funkioniert ja auch alles wunderbar. nur eben das letzte Ende ist falsch.

Hallo herbivore,

ich hatte in meinem Pattern noch nie lerrzeichen drin stehen. Und wie oben erwähnt, wenn ich die einsetze, matcht gar nix mehr.

Ich hab jetzt mal nur "([0-9]+) ([0-9]+)" hier ein leerzeichen eingesetzt, dann trifft auch nichts mehr...

Vielen dank für eure hilfe, aber nun bin ich verwirrt 🙁

Kalleberlin

If u want to finish first, u have to finish first.
49.485 Beiträge seit 2005
vor 15 Jahren

Hallo Kalleberlin,

siehe mein PS

herbivore

K
Kalleberlin Themenstarter:in
165 Beiträge seit 2007
vor 15 Jahren

Hallo herbivore,

zwischen den letzen beiden Ziffern ist definitv immer (mindestens) ein Lerrzeichen.

Die Ausgangssituation ist so wie ich sie euch geschildert habe.

Kalleberlin

If u want to finish first, u have to finish first.
49.485 Beiträge seit 2005
vor 15 Jahren

Hallo Kalleberlin,

da ist definitiv kein Leerzeichen im Input-String zum Zeitpunkt des Matchs. Das zeigt sich doch schon alleine daran, dass es keinen Match mehr gibt, wenn du ein Leerzeichen in den Pattern einfügst. Wenn du Regex-Lab nicht vertraust, schreib ein kleines Testprogramm mit der Eingabe "3 90" und "390" und den Pattern "([0-9]+) ([0-9]+)" und "([0-9]+)([0-9]+)" und allen Kombinationen daraus.

herbivore

B
5 Beiträge seit 2008
vor 15 Jahren

Unabhängig von deinem Problem ...
Kannst du mir mal erklären was du zb. mit [0-9999]{4} bezweckst ?
In der eckigen Klammer gibts du gültige Zeichen an, dass würe für dein Beispiel bedeuten, dass die Zeichen 0-9 , 9, 9 und 9 gültig sind 😉.
Hier reicht ein 0-9 vollkommen aus oder gleich ein @"\d{4}".

K
Kalleberlin Themenstarter:in
165 Beiträge seit 2007
vor 15 Jahren

Hallo alle,

also ich hab es jetzt so gelöst, das ich alle "lerrräume" die länger als 1 leerzeichen sind auf 1 gekürzt habe. so matcht er auch alles richtig wenn ich die leerzeichen ins pattern reinschreibe.

danke für eure hilfe.

@Benni83,

danke für den Tip, ich bin noch ziemlich blutiger anfänger in regex.

BTW: ich bin bis jetzt auch nicht davon überzeugt. langsam, schwer in der handhabung - da ist es für mich persönlich leichter das per hand zu implementieren. schneller wäre es dann auch. denke das war vorerst mein letzter regex ausflug^^

Kalleberlin

If u want to finish first, u have to finish first.
49.485 Beiträge seit 2005
vor 15 Jahren

Hallo Kalleberlin,

also ich hab es jetzt so gelöst, das ich alle "lerrräume" die länger als 1 leerzeichen sind auf 1 gekürzt habe. so matcht er auch alles richtig wenn ich die leerzeichen ins pattern reinschreibe.

was - so lese ich zwischen den Zeilen - bedeutet, dass du sie vorher auf 0 Leerzeichen gekürzt hattest. Insofern lag ich also doch richtig. 😃

Aber das Kürzen kannst du dir sparen. Schreibt statt " " einfach " +" oder "\s+" an die entsprechenden Stellen in den Pattern.

ich bin bis jetzt auch nicht davon überzeugt.

Schade, Regex ist wirklich super simpel, weil man ja meistens einfach nur Zeichen für Zeichen durch einen Beispiel-Input-String durchgehen muss und in den Pattern jeweils die entsprechende Zeichen-Klasse (z.B. \d) einträgt und dabei ab und zu noch ein paar Wiederholungszeichen (*, + {n}) oder Gruppen () einstreut. Wenn man das im Regex-Lab macht, dann man dabei sofort nachvollziehen, welcher Teil des Input-Strings durch den Pattern schon abgedeckt ist und ob man noch auf dem richtigen Weg ist.

Den Teil @"([0-99]{2}/[0-99]{2}/[0-9999]{4})" würde ich z.b. einfach als @"(\d\d/\d\d/\d\d\d\d)" schreiben. \d\d ist kürzer als \d{2}, einzig bei \d\d\d\d könnte man überlegen \d{4} zu schreiben. Einfacher geht es eigentlich nicht mehr. Wenn du das von Hand implementierst, wird es wesentlich aufgebläht.

herbivore

B
5 Beiträge seit 2008
vor 15 Jahren

Wenn du dich ein wenig mit Regex beschäftigst willst du es garantiert nicht mehr missen. Es gibt einfach keine einfachere und elegantere Möglichkeit Strings zu überprüfen.

Edit: Hier mal das Pattern etwas verkürzt:

string SearchPattern = @"^\d\d/\d\d/\d{4} " +
                       @"(\d\d:\d\d:\d\d\.\d\d ){2}" +
                       @"[A-Z] "+
                       @"\d{4}_\d{16} " +
                       @"[A-Z]\d " +
                       @"\d+ " +
                       @"\d+$";
K
Kalleberlin Themenstarter:in
165 Beiträge seit 2007
vor 15 Jahren

Hallo herbivore,

Insofern lag ich also doch richtig. 🙂

Das is ja das schlimme, Du hast fast immer recht 😄.

@Benni83,

da stimme ich Dir voll und ganz zu. Aber es ist halt auch so, solange man die genaue Syntax nicht kennt, kann man sich eben auch eine ganze menge Ärger einfangen.

Und Fakt ist auch, Regex ist ziemlich langsam!

Kalleberlin

If u want to finish first, u have to finish first.
G
497 Beiträge seit 2006
vor 15 Jahren

Hallo GarlandGreene,

tu dir selbst einen Gefallen und schau dir in aller Ruhe ein Tutorial zu regulären Ausdrücken an. Ich kann das hier als Einstieg empfehlen.

PS: Ja ich hab das Regex-Tutorial hier im Forum schon gelesen, komme aber leider trotzdem nicht weiter...

herbivore

das Tutorial behandelt aber speziell Charakterklassen aber nur relativ kurz, von daher habe ich ein etwas ausführlicheres und weniger auf die Programmierung mit C# bezogenes Tutorial verlinkt.