calim3ro
Goto Top

VBS-Entfernen von Zeilen in einer Textdatei

Hallo zusammen

Ich möchte aus einer Textdatei Zeilen entfernen. Ich habe drei Dateien, in Datei "A" stehen Wörter, in Datei "B" sind Zahlen und Wörter enthalten, in Datei "C" sind Zahlen.

Beispiele:

Datei "A"

Bus
Auto
...

Datei "B"

1234567 Bus
2345678 Motorrad
3456789 Auto
4567890 Fahrrad
...

Datei "C"

AA 1234567
BB 1234567
AA 2345678
BB 2345678
AA 3456789
AA 4567890
...

Wie müsste ein Skript aussehen, das die Datei "A" einliest, in der Datei "B" nach dem entsprechenden Wort sucht, die Zahl vor dem entsprechenden Wort merken, in Datei "C" nach der Zahl suchen und diese Zeile löschen, jedoch nur wenn AA vorneweg steht? (die Zahl kann auch in einem anderen Zusammenhang in Datei "C" vorkommen und sollte nicht entfernt werden.)

Bin für jeden Lösungsansatz oder Input dankbar.

Bei Unklarheiten bitte nachfragen.

Gruss Calimero

Content-Key: 234686

Url: https://administrator.de/contentid/234686

Printed on: April 20, 2024 at 14:04 o'clock

Mitglied: 115420
115420 Apr 06, 2014 updated at 20:30:55 (UTC)
Goto Top
Hallo Calimero!

Könnte hiermit funktionieren:
Option Explicit

Const FileA = "E:\Test\DateiA.txt"	'Pfade anpassen  
Const FileB = "E:\Test\DateiB.txt"  
Const FileC = "E:\Test\DateiC.txt"  

Dim oFso, oRe, oMatch, aTextA, sTextA, sTextB, sTextC, sNumber
    
Set oRe = New RegExp
Set oFso = CreateObject("Scripting.FileSystemObject")  
    
aTextA = Split(oFso.OpenTextFile(FileA).ReadAll, vbNewLine)
sTextB = oFso.OpenTextFile(FileB).ReadAll
sTextC = oFso.OpenTextFile(FileC).ReadAll
    
With oRe
   .Global = False
   .IgnoreCase = False
        
    For Each sTextA In aTextA
        If Trim(sTextA) <> "" Then  
           .Pattern = "(\d+)\s+" & sTextA  
                
            Set oMatch = .Execute(sTextB)
                
            If oMatch.Count Then
                sNumber = oMatch(0).SubMatches(0)
               .Pattern = "AA\s+" & sNumber & "\r?\n?"  
                    
                Set oMatch = .Execute(sTextC)
                    
                If oMatch.Count Then
                    sTextC = Replace(sTextC, oMatch(0).Value, "")  
                End If
            End If
        End If
    Next
End With

oFso.CreateTextFile(FileC).Write sTextC

MsgBox "Habe Fertig!"  

Grüße

Der Ratsuchende
Member: Calim3ro
Calim3ro Apr 06, 2014 at 20:13:56 (UTC)
Goto Top
Hallo Ratsuchender (eigentlich bin ja ich das face-smile)

Besten Dank für dein Skript, habe die Pfade entsprechend angepasst.

Jedoch gibt mit Windows Script Host einen Fehler aus. (Variable sTextB nicht definiert)

Habe nach kurzen Recherche im I-Net das "Option Explicit" und "Const" entfernt, nun motzt Windows Script Host nicht mehr.

Dafür hängt sich nach einiger Zeit der Windows Script Host auf. (Windows Based Script Host funktioniert nicht mehr)

Kann das mit der Grösse von Datei C zusammenhängen? (1.5 GB gross)

Kann man das Skript so umschreiben, dass bereits geprüfte Zeilen in ein anderes File geschrieben werden (Datei D) und die, welche dem Kriterium aus Datei A entsprechen, nicht?

Könnte dies das Problem mit Windows Script Host beheben?

Besten Dank für deine Bemühungen.

Grüsse Calimero
Member: Xaero1982
Xaero1982 Apr 06, 2014 updated at 20:51:59 (UTC)
Goto Top
Komisch, denn sTextB ist ganz klar definiert in der

dim oFso, oRe, oMatch, aTextA, sTextA, sTextB, sTextC, sNumber 
Zeile. Und Const sollte hier auch nicht das Problem sein bei Option Explicit.

Sorry, aber EINE Textdatei mit einer Größe von 1,5 GB? Die kann man eigentlich nur noch in die Tonne treten. Ich wüsste nicht welches Programm das öffnen soll.

Du solltest zunächst mal versuchen die Datei C zu verkleinern via script in dem du sie Zeilenweise einliest und ka 100 Zeilen oder so in eine neue Textdatei schreibst - von mir aus auch 1000 oder so.

Gruß
ps: Wenn das mit dem splitten nicht geht könntest du versuchen alle drei Dateien in eine Datenbank zu schreiben und dort diesen Vergleich mit einer Abfrage durchzuführen.
Member: bastla
bastla Apr 06, 2014 updated at 21:52:49 (UTC)
Goto Top
Hallo Calim3ro!

Unter der Annahme, dass die Zahlen in DateiB immer gleich lang sind (in Deinem Beispiel 7 Stellen - siehe Zeile 9), könnte das auf Basis des Ansatzes von DerRatsuchende etwa so gehen:
Option Explicit

Const FileA = "E:\Test\DateiA.txt"	'Pfade anpassen  
Const FileB = "E:\Test\DateiB.txt"  
Const FileC = "E:\Test\DateiC.txt"  
Const FileN = "E:\Test\DateiNeu.txt"  

Const Prefix = "AA "  
Const LenNumber = 7

Dim oFso, oRe, oMatch, aTextA, sTextA, sTextB, sNumber, oDict, sKey, iLenPre, iLenKey, oFileC, oFileN, sLine
    
Set oRe = New RegExp
Set oFso = CreateObject("Scripting.FileSystemObject")  
Set oDict = CreateObject("Scripting.Dictionary")  

iLenPre = Len(Prefix)
iLenKey = iLenPre + LenNumber
    
aTextA = Split(oFso.OpenTextFile(FileA).ReadAll, vbNewLine)
sTextB = oFso.OpenTextFile(FileB).ReadAll
    
With oRe
   .Global = False
   .IgnoreCase = False
        
    For Each sTextA In aTextA
        If Trim(sTextA) <> "" Then  
           .Pattern = "(\d+)\s+" & sTextA  
                
            Set oMatch = .Execute(sTextB)
                
            If oMatch.Count Then
                sNumber = oMatch(0).SubMatches(0)
                sKey = Prefix & sNumber
                If Not oDict.Exists(sKey) Then oDict.Add sKey, sTextA
            End If
        End If
    Next
End With

Set oFileC = oFso.OpenTextFile(FileC)
Set oFileN = oFso.CreateTextFile(FileN)
Do While Not oFileC.AtEndOfStream
    sLine = oFileC.ReadLine
    If Left(sLine, iLenPre) = Prefix Then
        sKey = Left(sLine, iLenKey)
        If Not oDict.Exists(sKey) Then oFileN.WriteLine sLine
    Else
        oFileN.WriteLine sLine
    End If    
Loop
MsgBox "Habe Fertig!"  
Es wird hier eine neue Datei erzeugt, die nur noch die gewünschten Zeilen enthält. Da die DateiC nicht komplett in den Arbeitsspeicher eingelesen wird, sollte die Dateigröße kein Problem sein ...

Ob das Prüfen der Zeilen aus DateiC auf den Zeilenanfang "AA " und erst bei Übereinstimmung der Vergleich der Nummer Performancevorteile bringt, müsstest Du selbst testen - das Script sähe alternativ so aus:
Option Explicit

Const FileA = "E:\Test\DateiA.txt"	'Pfade anpassen  
Const FileB = "E:\Test\DateiB.txt"  
Const FileC = "E:\Test\DateiC.txt"  
Const FileN = "E:\Test\DateiNeu.txt"  

Const Prefix = "AA "  
Const LenNumber = 7

Dim oFso, oRe, oMatch, aTextA, sTextA, sTextB, sNumber, oDict, sKey, iLenPre, iLenKey, oFileC, oFileN, sLine
    
Set oRe = New RegExp
Set oFso = CreateObject("Scripting.FileSystemObject")  
Set oDict = CreateObject("Scripting.Dictionary")  

iLenPre = Len(Prefix)
iLenKey = iLenPre + LenNumber
    
aTextA = Split(oFso.OpenTextFile(FileA).ReadAll, vbNewLine)
sTextB = oFso.OpenTextFile(FileB).ReadAll
    
With oRe
   .Global = False
   .IgnoreCase = False
        
    For Each sTextA In aTextA
        If Trim(sTextA) <> "" Then  
           .Pattern = "(\d+)\s+" & sTextA  
                
            Set oMatch = .Execute(sTextB)
                
            If oMatch.Count Then
                sNumber = oMatch(0).SubMatches(0)
                sKey = Prefix & sNumber
                If Not oDict.Exists(sKey) Then oDict.Add sKey, sTextA
            End If
        End If
    Next
End With

Set oFileC = oFso.OpenTextFile(FileC)
Set oFileN = oFso.CreateTextFile(FileN)
Do While Not oFileC.AtEndOfStream
    sLine = oFileC.ReadLine
    sKey = Left(sLine, iLenKey)
    If Not oDict.Exists(sKey) Then oFileN.WriteLine sLine
Loop
MsgBox "Habe Fertig!"  
Grüße
bastla
Mitglied: 115420
115420 Apr 07, 2014 updated at 10:22:42 (UTC)
Goto Top
Guten Morgen!

Komisch, denn sTextB ist ganz klar definiert in der
Sorry, war es nicht (*erwischt*)face-smile

Hatte gestern Abend bevor ich in's Bett ging, in der Dim-Zeile noch schnell ein abhanden gekommenes Komma eingefügt und wollte es auch kommentieren, hab's dann aber erstmal sein lassen, weil mir zu den 1,5 GB nix eingefallen war, zumal ich gedanklich schon im Bett warface-wink

bastlas Lösungsvorschläge finde ich gutface-wink Wie es mit der Perfomance aussieht ist allerdings eine andere Frage?


Grüße

spatzenhirn (DerRatsuchende)