Benutzer mit den meisten Antworten
Reguläre Ausdrücke

Frage
-
Hallo,
ich habe eine ; getrennte CSV-Datei. In einigen Zeilen gibt es jedoch manuelle falsch gesetzte Strichpunkte.
zb: ;999999;;;8888;"Text; Text";10,20;0;0;;;;;;
oder ;999999;;;8888;"Text; Text; Text";10,20;0;0;;;;;;
oder ;999999;;;8888;"Text; Text; ";10,20;0;0;;;;;;
Die "falschen" Strichpunkte stehen jedoch mmer zwischen 2 Anführungszeichen.
Welchen regulären Ausdruck müsste ich verwenden bzw. kann man dies mit regulären Ausdrücken lösen.
Ich würde gerne die Datei in eine Stringvariable lesen, die "falschen" Strichpunkte entfernen und dann die Datei wieder schreiben.
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click MsgBox("Start", MsgBoxStyle.Information, "Info") Dim Vpattern as String = (("[^"]*")) Dim Vpattern2 As String = ";" Dim replacement As String = "§" Dim rgx As New Regex(Vpattern2) Dim VFileText() As String = File.ReadAllLines("D:\testen\Alt.csv") For Each VLine In VFileText Dim matches As MatchCollection = Regex.Matches(VLine, Vpattern2) For Each m As Match In matches rgx.Replace(m.Value, replacement) Next End Using My.Computer.FileSystem.WriteAllText("D:\testen\Neu.csv", VFileText, False) MsgBox("Ende", MsgBoxStyle.Information, "Info") End Sub
Vielleicht hat ja jemand eine Lösung bzw. einen Lösungsansatz.
Vielen Dank schon im Voraus dafür.
Wolfgang
- Bearbeitet Anthony von LA Donnerstag, 23. Juli 2015 16:37
Antworten
-
Hallo Wolfgang,
es gibt sicher bessere Wege, das zu tun, hier aber mal eine mögliche Variante:
Dim Result As String Result = "<DerInhaltDerCsvDatei>" Dim Matches As MatchCollection Matches = Regex.Matches( Result, "\"".*;.*\""", RegexOptions.IgnoreCase Or RegexOptions.Multiline ) For Each Item As Match In Matches Result = Result.Replace( Item.Value, Item.Value.Replace( ";", "|||" ) ) Next Return Result
Allerdings sind die Semikola innerhalb der Anführungszeichen nicht falsch. Der Inhalt des Felds ist korrekterweise in doppelte Anführungszeichen eingeschlossen, daher darf der Feldtrenner auch im Wert selbst vorkommen. Die wenigsten Anwendungen haben damit Probleme.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community- Als Antwort markiert Anthony von LA Freitag, 24. Juli 2015 13:33
-
Hallo,
vielen Dank für die schnelle Unterstützung.
Wie Stefan bereits richtg bemerkt hat, ist nicht mehr praktiabel die komplette Datei in eine String-Variable zu laden, die Ersetzungen zu machen und die Datei zurück zu schreiben.
Das Programm brauchte ca 20 Sekunden bis es ein paar Ersetzungen (ca 200) durchlaufen hat.
Mit dem Pattern von Stefan wurden leider auch Stellen ersetzt, die nicht ersetzt werden sollten.
Ich verwende die nachfolgende Lösung:
Imports System.Text.RegularExpressions Imports System.IO
Dim VPAT As String = "(" & "(" & """" & "[" & "^" & """" & "]" & "*" & """" & ")" & ")" Dim Result As String
Dim sr As StreamReader = New StreamReader("D:\testen\alte.csv") Dim wr As StreamWriter = New StreamWriter("D:\testen\neue.csv", False)
Dim Matches As MatchCollection Do Until sr.Peek() = -1 Result = sr.ReadLine Matches = Regex.Matches(Result, VPAT, RegexOptions.IgnoreCase Or RegexOptions.Multiline) For Each Item As Match In Matches Result = Result.Replace(Item.Value, Item.Value.Replace(";", ":")) Next wr.WriteLine(Result) Loop sr.Close() wr.Close()
Mit dem Pattern in der Variable VPAT werden alle Stellen gefunden, wo Zeichen zwischen Anführungszeichen stehen.
Vielen Dank noch einmal an Stefan. Du hast mich auf den richtigen Weg gebracht.
Besten Grüßen
Wolfgang
- Als Antwort markiert Anthony von LA Freitag, 24. Juli 2015 13:33
Alle Antworten
-
Hallo Wolfgang,
es gibt sicher bessere Wege, das zu tun, hier aber mal eine mögliche Variante:
Dim Result As String Result = "<DerInhaltDerCsvDatei>" Dim Matches As MatchCollection Matches = Regex.Matches( Result, "\"".*;.*\""", RegexOptions.IgnoreCase Or RegexOptions.Multiline ) For Each Item As Match In Matches Result = Result.Replace( Item.Value, Item.Value.Replace( ";", "|||" ) ) Next Return Result
Allerdings sind die Semikola innerhalb der Anführungszeichen nicht falsch. Der Inhalt des Felds ist korrekterweise in doppelte Anführungszeichen eingeschlossen, daher darf der Feldtrenner auch im Wert selbst vorkommen. Die wenigsten Anwendungen haben damit Probleme.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community- Als Antwort markiert Anthony von LA Freitag, 24. Juli 2015 13:33
-
Hallo Stefan,
vielen Dank für die schnelle Antwort. Ich habe versucht deine Lösung zu verwenden.
Leider fliegt mir das Programm dabei auf das Näschen:
Zusätzliche Informationen: Die CLR konnte 60 Sekunden lang keinen Übergang vom COM-Kontext 0x149ffa0 zum COM-Kontext 0x14a0058 durchführen.
Vielleicht habe ich vor lauter Probieren doch noch etwas übersehen?
Die "falschen" Strichpunkte werden von Mitarbeitern eingeben, die im Textfeld mit Caps Lock schreiben.
Die Datei hat ca. 60.000 Zeilen und muss tgl. neu ins DWH per BULK-Insert verarbeitet werden.
MsgBox("Start", MsgBoxStyle.Information, "no nicht getan") Dim Result As String Result = My.Computer.FileSystem.ReadAllText("D:\testen\alte.csv") Dim Matches As MatchCollection Matches = Regex.Matches(Result, "\"".*;.*\""", RegexOptions.IgnoreCase Or RegexOptions.Multiline) For Each Item As Match In Matches Result = Result.Replace(Item.Value, Item.Value.Replace(";", "|||")) Next My.Computer.FileSystem.WriteAllText("D:\testen\Neu.csv", Result, False)
-
Hallo Wolfgang,
bei so vielen Zeilen ist eine normale Stringersetzung nicht mehr praktikabel, da das intern zu viele Ressourcen verbrät.
Daher hier eine Variante mit einem StringBuilder, die sollte problemlos laufen.
Dim SB As New StringBuilder() Dim Matches As MatchCollection Matches = Regex.Matches( Value, "(.*)(\"".*;.*\"")(.*)", RegexOptions.IgnoreCase Or RegexOptions.Multiline ) For Each Item As Match In Matches SB.Append( Item.Groups( 1 ).Value & Item.Groups( 2 ).Value.Replace( ";", "|||" ) & Item.Groups( 3 ).Value ) Next Return SB.ToString()
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community- Als Antwort vorgeschlagen Stefan FalzModerator Montag, 27. Juli 2015 17:22
-
Hallo,
vielen Dank für die schnelle Unterstützung.
Wie Stefan bereits richtg bemerkt hat, ist nicht mehr praktiabel die komplette Datei in eine String-Variable zu laden, die Ersetzungen zu machen und die Datei zurück zu schreiben.
Das Programm brauchte ca 20 Sekunden bis es ein paar Ersetzungen (ca 200) durchlaufen hat.
Mit dem Pattern von Stefan wurden leider auch Stellen ersetzt, die nicht ersetzt werden sollten.
Ich verwende die nachfolgende Lösung:
Imports System.Text.RegularExpressions Imports System.IO
Dim VPAT As String = "(" & "(" & """" & "[" & "^" & """" & "]" & "*" & """" & ")" & ")" Dim Result As String
Dim sr As StreamReader = New StreamReader("D:\testen\alte.csv") Dim wr As StreamWriter = New StreamWriter("D:\testen\neue.csv", False)
Dim Matches As MatchCollection Do Until sr.Peek() = -1 Result = sr.ReadLine Matches = Regex.Matches(Result, VPAT, RegexOptions.IgnoreCase Or RegexOptions.Multiline) For Each Item As Match In Matches Result = Result.Replace(Item.Value, Item.Value.Replace(";", ":")) Next wr.WriteLine(Result) Loop sr.Close() wr.Close()
Mit dem Pattern in der Variable VPAT werden alle Stellen gefunden, wo Zeichen zwischen Anführungszeichen stehen.
Vielen Dank noch einmal an Stefan. Du hast mich auf den richtigen Weg gebracht.
Besten Grüßen
Wolfgang
- Als Antwort markiert Anthony von LA Freitag, 24. Juli 2015 13:33
-
Hallo Wolfgang,
probier aber doch nochmal die Variante mit dem StringBuilder, die ist erheblich schneller.
Wenn Du uns verrätst, welche Probleme noch bei den Ersetzungen bestehen, kann man den Regex Ausdruck sicher noch anpassen.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community