Autor |
Beitrag |
mannyk
      
Beiträge: 83
Erhaltene Danke: 1
|
Verfasst: Fr 06.02.09 10:10
Hi,
Ich habe folgendes Problem: Ich möchte eine Zeile beim Komma splitten, aber nur, wenn wenn das Komma nicht innerhalb von Gänsefüsschen steht.
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| test1,test2,"test3",test4,"te,st5","te,st6"
soll in:
test1 test2 "test3" test4 "te,st5" "te,st6" |
Ich war schon extrem lange dran, hab es leider nicht hinbekommen.
Liebe Grüsse
|
|
bakachan
      
Beiträge: 503
Erhaltene Danke: 34
W7 (x64) Ultimate
C# / VB.NET (VS2010 Ultimate)
|
Verfasst: Fr 06.02.09 10:34
Was hast du denn schon versucht und woran genau hängt es?
Du hast dabei doch nur 2 Fälle die du beachten musst:
1. Ein zusammenhängender Text der keine ',' enthält
2. Ein Test der in ' " ' steht und somit auch ',' egal wäre(falls vor und nach den ' " ' noch Text stehen kann musst du das natürlich auch beachten)
|
|
mannyk 
      
Beiträge: 83
Erhaltene Danke: 1
|
Verfasst: Fr 06.02.09 10:48
Hi, ich habe foldendes probiert. Bin in den Regex auch nicht so gut...
,(?=\")|(?<=\"),
Das Pattern trennt alles, aber nicht die ganz normalen Fälle, wo gar keine Gänsefüsschen vorkommen.
lg
|
|
bakachan
      
Beiträge: 503
Erhaltene Danke: 34
W7 (x64) Ultimate
C# / VB.NET (VS2010 Ultimate)
|
Verfasst: Fr 06.02.09 11:01
,(?=\")|(?<=\"),
trennt nur da wo direkt danach oder davor ein ' " ' steht
entspricht also nicht den anforderungen
für .Matches wäre [^,]*?".*?"[^,]*?|[^,]+ der richtige Regex.
Den Umbau für eine Splitfunktion kannst du ja selbst noch machen
|
|
mannyk 
      
Beiträge: 83
Erhaltene Danke: 1
|
Verfasst: Fr 06.02.09 11:17
Hallo,
erstmal tausend Dank für die Antwort!
hm, ich überleg grad, was ich für das splitting ändern muss.
Benutze ich es so, wie es jetzt ist, beinhaltet das gesplittete Array nur die 5 Kommatas.
Falls du also noch einen Tipp hättest, wäre das super!
lg
|
|
bakachan
      
Beiträge: 503
Erhaltene Danke: 34
W7 (x64) Ultimate
C# / VB.NET (VS2010 Ultimate)
|
Verfasst: Fr 06.02.09 11:33
Wie gesagt mein Regex da oben ist für .Matches und nicht für .Split gedacht.
Aber ich will dir ja auch nicht die ganze arbeit abnehmen 
|
|
martin300
      
Beiträge: 186
Erhaltene Danke: 2
|
Verfasst: Fr 06.02.09 13:40
Warum soll bei so einem einfachen Beispiel reguläre Ausdrücke genommen werden? Das geht doch viel schneller, wenn es als String mit pos und copy bearbeitet wird.
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Fr 06.02.09 13:51
Da bin ich mal gespannt. Etwas mehr als 5 Zeilen wirst du dafür sicher benötigen, mit einem Regex hast du es in einer. Und die ist aus Compiler-theoretischer Sicht unendlich eleganter  .
_________________ >λ=
|
|
mannyk 
      
Beiträge: 83
Erhaltene Danke: 1
|
Verfasst: Fr 06.02.09 14:06
Naja, du hast ja irgendwie recht.
Ich habe nun folgendes gemacht.
Der Ausdruck ist mit einem Oder verknüpft. Nun habe ich beide Teile in einen lookahead Ausdruck getan (da nur das Komma entfernt werden soll).
,(?= [^,]*?\".*?\"[^,]*?) | ,(?= [^,]+)
Leider wird nun wieder der Ausdruck "te,st5" auch gesplittet.
|
|
martin300
      
Beiträge: 186
Erhaltene Danke: 2
|
Verfasst: Fr 06.02.09 14:12
Es es nötig das es eine Unit für Reguläre Ausdrücke in Delphi gibt. Ich konnte in Turbo Delphi kein finden. Daher eine herunterladen. Da ich mich mit regulären Ausdrücken nicht auskenne, muss in der Bedeutung der einzelnen Zeichen nachgesehen - gesucht werden.
Bei so einem Ausdruck ist es eine Schleife mit der Abfrage, ob ein '"' davor war oder nicht. Es sind mehr als 5 Zeilen, aber nicht viel mehr.
Keine Ahnung was du mit "Compiler-theoretischer Sicht" meinst. Aber ich bin gerne offen und würde gerne weitere Vorteile kennen.
|
|
mannyk 
      
Beiträge: 83
Erhaltene Danke: 1
|
Verfasst: Fr 06.02.09 15:14
Kann mir sonst villeicht jemand helfen?
Es ist doch ziemlich dringend und ich habe keine Idee..
lg
|
|
PerryRhodan
      
Beiträge: 34
C# (VS 2005 + 2008), .NET 2.0 + 3.5 (inkl. WPF, WCF)
|
Verfasst: Fr 06.02.09 16:01
Hallo,
nur ein kleiner Tipp am Rande:
www.radsoftware.com.au/regexdesigner/
Ich weiß nicht, ob Du das kennst aber es hat mir immer gute Dienste geleistet, wenn es um das Zusammenschrauben von Regular Expressions ging.
Jetzt nur noch die Logik aufsetzen, übersetzen und testen.
Grüße
PerryRhodan
_________________ C# im IRC: QuakeNet, Channel: #dotNet.de
|
|
danielf
      
Beiträge: 1012
Erhaltene Danke: 24
Windows XP
C#, Visual Studio
|
Verfasst: Fr 06.02.09 16:45
Hallo,
falls du es nicht unbedingt mit split machen musst könntest du es wie folgt parsen:
c# 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| List<string> lsResultStrings = new List<string>(); string sInput = "test1,test2,\"test3\",test4,\"te,st5\",\"te,st6\""; string sPattern = "\"(.*?)\",?|,?(.*?),"; Regex oRegularExpression = new Regex(sPattern); MatchCollection oMatches = oRegularExpression.Matches(sInput);
foreach (Match oMatch in oMatches) { // check which group successed and add value to // result list if (oMatch.Groups[1].Success) { lsResultStrings.Add(oMatch.Groups[1].Value); } else { lsResultStrings.Add(oMatch.Groups[2].Value); } } |
@bakachan: Dein Pattern hab ich auch mal probeweise eingefügt, war aber nicht erfolgreich :/
Gruß, Daniel
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Fr 06.02.09 16:54
mannyk hat folgendes geschrieben : | Kann mir sonst villeicht jemand helfen? |
Das Problem ist mit Split wahrscheinlich überhaupt nicht zu bewältigen, da du eben wegen der Anführungszeichen nicht "irgendwo" mit dem Matchen anfangen kannst. Ich würde also einen normalen Match wie ^(([^",]+|"[^"]*")(,|$))* losschicken (so finde ich ihn am aussagekräftigsten, ich kann ihn auch gerne mal zerlegen) und dann alle Treffer der inneren vorderen Klammer zurückgeben. Für eine genauere Beschreibung müsstest du einmal deine Regex-Engine verraten.
/add: Also so etwa, wie es danielf macht  .
martin300 hat folgendes geschrieben : | Es es nötig das es eine Unit für Reguläre Ausdrücke in Delphi gibt. Ich konnte in Turbo Delphi kein finden. Daher eine herunterladen. Da ich mich mit regulären Ausdrücken nicht auskenne, muss in der Bedeutung der einzelnen Zeichen nachgesehen - gesucht werden. |
mannyk hat ja wohl schon eine installiert. Und dass man Schwierigkeiten mit etwas hat, mit dem man sich nicht auskennt, trifft möglicherweise nicht nur auf reguläre Ausdrücke zu  . Ich denke, Regexes werden heute durchaus als Standard-Handwerkzeug von Programmierern angesehen, sich mit ihnen zu beschäftigen ist also sicher keine Vergeudung. Aber wer überzeugt ist, ohne sie schneller voranzukommen, der soll auch ruhig darauf verzichten. Denn irgendwo trifft das berühmte Standardzitat zu Regexes natürlich zu  .
martin300 hat folgendes geschrieben : | Bei so einem Ausdruck ist es eine Schleife mit der Abfrage, ob ein '"' davor war oder nicht. |
So einfach ist es leider nicht. Wenn du "direkt davor" meinst, wäre a,",b" ein Gegenbeispiel.
martin300 hat folgendes geschrieben : | Keine Ahnung was du mit "Compiler-theoretischer Sicht" meinst. Aber ich bin gerne offen und würde gerne weitere Vorteile kennen. |
Anders gesagt: Der Regex ist rein deklarativ: Er beschreibt das Problem als formale Sprache, um die Umsetzung kümmert sich die Regex-Engine. Pos und Copy sind dagegen rein imperativ; das was wird durch das wie verdrängt. Und nicht nur Haskell-Programmierer dürften deklarativen Code lieben  .
_________________ >λ=
|
|
bakachan
      
Beiträge: 503
Erhaltene Danke: 34
W7 (x64) Ultimate
C# / VB.NET (VS2010 Ultimate)
|
Verfasst: Fr 06.02.09 17:03
danielf hat folgendes geschrieben: | @bakachan: Dein Pattern hab ich auch mal probeweise eingefügt, war aber nicht erfolgreich :/
Gruß, Daniel |
Habs mal fix im Regex-Lab getestet mein Regex funktioniert darin.
Und an Kha:
doch es geht auch mit .Split man muss halt nur nach den Kommatas suchen die nicht in Anführungszeichen stehen.
Naja obwohl ich normalerweise nicht gerne die fertigen Lösungen gebe hier mal der Regex für .Split:
(?<!^[^"]*"[^"]*("[^"]*"[^"]*)*),
(kann man bestimmt noch etwas übersichtlicher machen indem mans zusammenfasst aber er erfüllt seinen Zweck)
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Fr 06.02.09 17:25
bakachan hat folgendes geschrieben : | doch es geht auch mit .Split man muss halt nur nach den Kommatas suchen die nicht in Anführungszeichen stehen. |
Hargh, den Absatz wollte ich doch noch löschen  . Deine Idee, zu schauen, ob ungradzahlig viele Anführungszeichen vor dem Komma stehen, gefällt mir  .
_________________ >λ=
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Fr 06.02.09 19:19
Kha hat folgendes geschrieben : | Da bin ich mal gespannt. Etwas mehr als 5 Zeilen wirst du dafür sicher benötigen, mit einem Regex hast du es in einer. Und die ist aus Compiler-theoretischer Sicht unendlich eleganter . |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| var I: Integer; begin with TStringList.Create do try Delimiter := ','; QuoteChar := '"'; StrictDelimiter := True; DelimitedText := 'test1,test2,"test3",test4,"te,st5","te,st6"'; for I := 0 to Count - 1 do ShowMessage(Strings[I]); finally Free; end; end; |
Die "handgestrickte" RegExp Lösung ist dafür nicht wirklich in wenigen Sekunden verstehbar und berücksichtigt nicht alle Fälle, die bei CSV Daten vorkommen können. So wird die Eingabe '"abc""def"' hier direkt zu 'abc"def", bei RegExp wäre da mehr nötig.
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Fr 06.02.09 20:24
Uuund wo hast du nun Pos+Copy benutzt  ?
Keine Frage, wenn eine Funktion schon vorhanden ist, nutzt man natürlich diese - deklarativer geht es gar nicht  . Besonders wenn sie Standards implementiert, an die man beim Rad-Neu-Erfinden gar nicht gedacht hätte, wie dein Beispiel zeigt.
_________________ >λ=
|
|
martin300
      
Beiträge: 186
Erhaltene Danke: 2
|
Verfasst: Sa 07.02.09 12:01
Deine Erklärung ist ganz gut. Die regulären Ausdrücke sind sicher für sehr viele Fälle interessant. Mich würde noch folgendes Interessieren. Wie sieht es da mit der Fehlerbehandlung aus? Wenn zb. zwei "" nacheinander kommen. Kommt diese Behandlung auch in den Ausdruck hinein, oder würde ein neuer Ausdruck angelegt?
|
|