VB.NET REGEX in Python - unexpected end of pattern

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

streetfox hat geschrieben:@rayo

Code: Alles auswählen

"that it
works ;"
as ""ss""
expected"" 
"And"
.... nö, das oben ist 1 Record und nicht 3, auch von hand
Bei mir startet er beim ersten Anführungszeichen in der ersten Zeile und endet in der 2. Zeile beim Schlusszeichen. Dann kommen Records, die die ganze Zeile lang sind.

Daher stimmt das schon mit 3 Records oder warum endet bei dir der Record nicht in der 2. Zeile beim Schlusszeichen?
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

Welcher Version der .net Laufzeitumgebung verwendest du denn? Auf jedenfall funktionierts mit IronPython auch nicht... und das verwendet exakt die selbe Bibliothek wie du.
streetfox
User
Beiträge: 18
Registriert: Dienstag 27. Januar 2009, 12:23

@Trundel

.NET 3.5 SP1

@rayo

problem ist, dass hier mit einem free-text feld gearbeitet wurde. Im system werden die sonderzeichen nicht sauber ausgewiesen....

z.B.

Code: Alles auswählen

" statt
\"
oder
LF (als zeichen)
statt
\n
somit ist der record nicht beim vermeintlichen zeilenumbruch innerhalb des "..."; feldes zuende, sondern bei Fall 3

also gibt es 3 Fälle für einen Datensatz
  • Fall1: " zu beginn des Files
    Fall2: ";" immer dazwischen
    Fall3: ;"..." + LF + "..."; Am Ende des Datensatzes
die RE erkennt dieses Muster. Wenn es uns gelingt das zu knacken kann ja jemand dafür sorgen dass dies in die stdlib vom CSV Parser eingepflegt wird?
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Also ich kapiers noch nicht wirklich, wann der Datensatz nun zu ende sein soll und wann nicht.

Wie kann man erkennen ob die Daten auf der nächsten Zeile zur vorherigen Zeile gehören? Immer wenn auf der neuen Zeile nur ein Feld ("...") ist, gehörts zum vorherigen Datensatz? (Was ist dann mit csv-Files mit einer Zelle?)
streetfox hat geschrieben:Wenn es uns gelingt das zu knacken kann ja jemand dafür sorgen dass dies in die stdlib vom CSV Parser eingepflegt wird?
Ich denke nicht, dass das jemals eingepflegt wird, denn so wie du es beschrieben hast, sind die Sonderzeichen nicht richtig ... sprich das Feld ist fehlerhaft.

Gruss
streetfox
User
Beiträge: 18
Registriert: Dienstag 27. Januar 2009, 12:23

Code: Alles auswählen

"...";"text der hier steht"
"...";"text der hier steht"
= 2 Datensätze

im Vergleich zu

Code: Alles auswählen

"...";"text der
hier steht"
"...";"text der hier steht"
= 2 Datensätze (multiline)

Felder die fehlerhaft sind gibts nun mal immer wieder.
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

streetfox hat geschrieben:

Code: Alles auswählen

"...";"text der hier steht"
"...";"text der hier steht"
= 2 Datensätze

im Vergleich zu

Code: Alles auswählen

"...";"text der
hier steht"
"...";"text der hier steht"
= 2 Datensätze (multiline)
Ja soweit ist mir das klar, angewendet auf dein Beispiel gibts halt wieder mehrere Datensätze:

Code: Alles auswählen

"that it
works ;"
Hier kommt nach dem Feld, welches nach works ;" endet, ein Zeilenumbruch und ein Zeilenumbruch ausserhalb eines Feldes ist gleich bedeutend mit einem neuen Datensatz.

Code: Alles auswählen

<feld anfang>"that it
works ;"<feld ende> <neuer datensatz (neue zeile ausserhalb feld)>
<feld anfang>as ""ss""<feld ende> <neuer datensatz>
<feld anfang>expected""<feld ende> <neuer datensatz>
<feld anfang>"And"<feld ende> <neuer datensatz>
Oder was mach ich falsch?

streetfox hat geschrieben:Felder die fehlerhaft sind gibts nun mal immer wieder.
Dies sollte aber nicht in einen Parser in der Standardbibliothek einfliessen.
streetfox
User
Beiträge: 18
Registriert: Dienstag 27. Januar 2009, 12:23

Oder was mach ich falsch?
joa das gleiche wo ich vorher immer reingefallen bin ;-)...

Code: Alles auswählen

works ;" <selbes Feld, neue Zeile>
as "ss"
auf linie 2 beginnt es nicht mit einem Gänsefüsschen = selbes Feld

Dies sollte aber nicht in einen Parser in der Standardbibliothek einfliessen.
joa, versteh ich schon...drum fragte ich hier nach einer REGEX ^^
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

streetfox hat geschrieben:@Trundel

.NET 3.5 SP1
1. Ich bin nicht Trundle. Immernoch nicht.
2. Hab nun VB.net Express 2008 geladen (benutzt .net 3.5sp1). Hab eine kleine Applikation gebastelt mit einer Textbox und einem Button. Wenn ich deinen Text da reinkopiert und auf den button klicke, wird dein code benutzt. Danach geb ich mit einer for each schleife jedes element der liste aus. Aber leider ist da nur ein Element drin - dein RegEx funktioniert nicht. Entweder du zeigst mir deine Applikation, wo der RegEx tatsächlich funktioniert oder... keine Ahnung, es passt einfach nich oO' Weder mit IronPython noch mit C# noch mit VB.net krieg ich'ne Applikation um dieses RegEx zustande oO'' entweder bin ich wirklcih arg unfähig heute oder du hast dich vertan.
BlackJack

@streetfox: Auch Dein letztes Beispiel ist unstrittig denke ich, aber warum das hier ein Datensatz, statt zwei sein soll, ist eben unklar:

Code: Alles auswählen

"that it
works ;"
as ""ss""
In der zweiten Zeile endet das mehrzeilige Feld und dann beginnt mit dem Zeilenende ein neuer Datensatz.

Wenn das nicht der Fall ist, würde ich's schon nicht mehr als CSV bezeichnen. Ich weiss es gibt keine allgemeingültige Definition, aber wenn's nicht von RFC4180 Common Format and MIME Type for Comma-Separated Values (CSV) Files abgedeckt ist, sollte es IMHO nicht in die Standardbibliothek.
streetfox
User
Beiträge: 18
Registriert: Dienstag 27. Januar 2009, 12:23

nja...

ein feld mit quoted text endet immer auf "; und nicht auf ;". Es sei denn am Ende des Datensatzes. Hier ist zu überprüfen ob die Zeichenfolge "\n"*"; folgt. Tut sie das, ist dies das Ende des Datensatzes. Ansonsten nur LF im Feld. Denn im zweiten fall gehört das semikolon und die füsschen zum feldtext. Ergo ist auch die zweite zeile nicht das ende des feldes, nicht.

jep, geb ich unumwunden zu, schönes CSV würd ichs nicht nennen. Die idee mit der stdlib hab ich ja ned aufgebracht. Und warum die RE bei Vivi nicht klappt oO noch rätselhafter
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

streetfox hat geschrieben:jep, geb ich unumwunden zu, schönes CSV würd ichs nicht nennen. Die idee mit der stdlib hab ich ja ned aufgebracht. Und warum die RE bei Vivi nicht klappt oO noch rätselhafter
Mach uns doch mal'ne schöne Applikation zurecht... Dann probieren wir die aus und analysierens und setzen es in IronPython um :)
streetfox
User
Beiträge: 18
Registriert: Dienstag 27. Januar 2009, 12:23

Gegenvorschlag:

Pfriemel die REGEX hier mal ein:

http://www.myregextester.com/index.php
übrigens ne tolle Seite!

(aktiviere VB.NET) lass die RE laufen.... du kriegst die richtigen Values immer im array [x][0] raus...

... bei python bin ich mittlerweile hier angelangt

Code: Alles auswählen

re.compile(r'"(?:""|[^"])*')
aber auch die verschluckt sich, dafür funzt sie garantiert in python
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

...Nein, es funktioniert nicht oO'

Bei mir zumindest nicht. Entweder ist dein RegEx im ersten Post falsch oder dein Text im .. 3ten Post von dir falsch kopiert. Keine Ahnung was, aber es kommt nur hühnerkacke heraus. Oder ich bin wirklich unfassbar unfähig im kopieren.

Code: Alles auswählen

Raw Match Pattern:
(?>([^,"]*("[^"]*")*[^,"]*)*)("[^"]*)?

VB.NET Code Example:
Imports System.Text.RegularExpressions
Module Module1
  Sub Main()
    Dim sourcestring as String = "replace with your source string"
    Dim re As Regex = New Regex("(?>([^,""]*(""[^""]*"")*[^,""]*)*)(""[^""]*)?")
    Dim mc as MatchCollection = re.Matches(sourcestring)
    Dim mIdx as Integer = 0
    For each m as Match in mc
      For groupIdx As Integer = 0 To m.Groups.Count - 1
        Console.WriteLine("[{0}][{1}] = {2}", mIdx, re.GetGroupNames(groupIdx), m.Groups(groupIdx).Value)
      Next
      mIdx=mIdx+1
    Next
  End Sub
End Module

Matches Found:
[0][0] = "Value1;";"Value2";"""Value3""";"of ""very"" ""difficult""";"";"expressions" 
"and";"";"we should not ;""then""; forget";"that it 
works ;" 
as ""ss"" 
expected"" 
"And";"this ""is""";" a";"new start" 
"And2";"this is a";"new start as well" 
"only "this" line";" is malformat;ted "with" quotes"
[0][1] = 
[0][2] = " quotes"
[0][3] = 
[1][0] = 
[1][1] = 
[1][2] = 
[1][3] = 
Klär mich auf, was mach ich falsch?
streetfox
User
Beiträge: 18
Registriert: Dienstag 27. Januar 2009, 12:23

ach je, aus meinem 2ten post:, nich zickig werden, ja :D
sie versucht sehr unschöne csv files zu parsen, ich benutze sie mit ";"

Code: Alles auswählen

(?>([^,"]*("[^"]*")*[^,"]*)*)("[^"]*)? (mit Komma)
!=

Code: Alles auswählen

(?>([^;"]*("[^"]*")*[^;"]*)*)("[^"]*)? (mit Semikolon)
kein wunder kriegst du hühnergagge. ^^

/edit ....ich geh mal den post korrigieren. Anscheinend reicht es nicht nur drauf hinzuweisen
/edit2 sorry mir war das soooo offensichtlich... [^,]... wieso sollte jemand nach NICHT Komma bei Semikolon-separierten einträgen suchen x__X
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

Aber auch so is der RE nich das Wahre oO' Kommt viel Müll drumherum heraus, quoting fällt raus scheinbar usw... Ich würde echt darüber nachdenken, was eigenes zu parsen oder so oO
streetfox
User
Beiträge: 18
Registriert: Dienstag 27. Januar 2009, 12:23

tjoo... drum bin ich hier im forum gelandet um zu gucken ob da jemand mehr weiss als ich, was ich oft annehme, da ich mit RE zwar schon einige Zeit arbeite aber mich nicht als crack bezeichnen würd. dafür issn forum ja da.

übrigens... hab sie nun umgeschrieben

Code: Alles auswählen

;(?=(?:[^"]*"[^"]*")*(?![^"]*"))
führt zu

Code: Alles auswählen

>>> text = '''"Value1;";"Value2";"""Value3""";"of ""very"" ""difficult""";"";"expressions"
"and";"";"we should not ;""then""; forget";"that it
works ;"
as ""ss""
expected""
"And";"this ""is""";" a";"new start"
"And2";"this is a";"new start as well"
"only "this" line";" is malformat;ted "with" quotes"'''

>>> ptest = re.compile(';(?=(?:[^"]*"[^"]*")*(?![^"]*"))')

>>> re.split(ptest,text)
['"Value1;"', '"Value2"', '"""Value3"""', '"of ""very"" ""difficult"""', '""', '"expressions"\n"and"', '""', '"we should not ;""then""; forget"', '"that it\nworks ;"\nas ""ss""\nexpected""\n"And"', '"this ""is"""', '" a"', '"new start"\n"And2"', '"this is a"', '"new start as well"\n"only "this" line"', '" is malformat;ted "with" quotes"']
funzt jetzt auch in python... jetzt bin ich schon nah dran bis auf

Code: Alles auswählen

..."\n"And"'
statt
..." ' , ' "And"'
det muss doch zum knacken sein?
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Machs nicht mit RegExp. Ich würd da entweder das cvs Modul anpassen, PyParsing nutzen oder nen Parser per Hand schreiben, ne FSM ist ja nicht so schwer und wohl etwas übersichtlicher.
Antworten