| Autor | Beitrag | 
| mannyk 
          Beiträge: 83
 Erhaltene Danke: 1
 
 
 
 
 | 
Verfasst: Fr 06.02.09 09: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 09: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 09: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 10: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 10: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 10: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 12: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 12: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 13: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 13: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 14: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 15: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 15: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 15: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 16: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 16: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 18: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:
 
 | varI: 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 19: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 11: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? | 
|  |