reinhr
Goto Top

Inhalt einer test.txt mit Inhalt einer Mapping.ini vergleichen und wenn Zeichenfolge identisch, test.txt mit Wert aus Mapping ini ersetzen

Hallo Forum,
hier wurde mir schon oft geholfen, ich hoffe das klappt diesmal auch.

Ich habe jeweils eine Datei 00001.txt fortlaufend automatisch hoch gezählt und erstellt wird.
Die Datei hat jeweils unterschiedliche Codes als Inhalt. Z.B.: xxxx|yyyy|1|4|1|6|zzzz
Die Dateistruktur ist immer gleich und besteht aus nur einer Zeile.
Ich möchte nun anhand einer Mappingtabelle (Mapping.ini) die Zeichen nach der 2. Pipe (1|4|1|6) durch einen Eintrag aus der Mappinddatei ersetzen.

Inhalt der Mapping Datei:

1|4|1|6=123456
1|4|1|5=234567
1|4|1|4=345600
usw. (ca. 200 Codes bzw. Zeilen)

Die Zeichenfolge wie "1|4|1|6" ist einzigartig und kommt in der Mapping Datei nur einmal vor.

Die BAT Datei die ich benötige soll in der "Mapping.ini" nach dem Wert "1|4|1|6" suchen der in der "00001.txt" steht und
diesen wenn gefunden durch den Wert 123456 ersetzen.

Abbruch des Programms wenn der Eintrag nicht gefunden wurde oder abbruch des restlichen Suchlaufs wenn gefunden wäre auch wichtig.

Kann mir jemand helfen?

Gruß
reinhr

Content-Key: 128995

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

Printed on: April 19, 2024 at 19:04 o'clock

Member: bastla
bastla Nov 09, 2009 at 20:55:23 (UTC)
Goto Top
Hallo reinhr!

Abgesehen davon, dass "Suchen/Ersetzen" ohnehin besser mit speziellen Tools wie "sed" oder zumindest per VBScript durchgeführt werden sollte, spricht auch die Anforderung "abbruch des restlichen Suchlaufs wenn gefunden" eher gegen eine Batch-Lösung.
Mir ist leider auch nicht ganz klar, wie der Ablauf selbst vorgesehen ist, insbesondere, ob einzig und allein der String "1|4|1|6" ersetzt werden soll oder doch für alle in der "Mapping.ini" vorkommenden Suchbegriffe Ersetzungen geplant sind. In ersterem Falle stellte sich vor allem die Frage, wie / wodurch festgelegt wird, wonach überhaupt gesucht werden soll.

Und: Wie groß ist die zu durchsuchende Textdatei? Soferne sie problemlos am Stück in den Arbeitsspeicher passt, sollte sich die Aufgabe per VBScript relativ einfach erledigen lassen.

Grüße
bastla
Member: reinhr
reinhr Nov 09, 2009 at 21:03:20 (UTC)
Goto Top
Hallo bastla,

die Mapping Datei ist ca. 10kb groß und es gibt max 300 zu durchsuchende Codes.
Die TXT Datei wird automatisch erstellt.
Direkt nach der Erstellung will ich die BAT anstoßen.
Diese konvertiert den Inhalt. (Alter Wert|Alte Wert|Konvertierter Wert|Alter Wert)
Die neue Datei wird danach verarbeitet und gelöscht.

Gruß
reinhr
Member: bastla
bastla Nov 09, 2009 at 21:21:09 (UTC)
Goto Top
Hallo reinhr!

Soferne ich das richtig herauslese, sollen in der TXT-Datei für alle Codes der Mapping-Datei Ersetzungen vorgenommen werden. In diesem Fall könnte ein VBScript etwa so aussehen:
File = "D:\00001.txt"  
Ini = "D:\Mapping.ini"  

Set fso = CreateObject("Scripting.FileSystemObject")  
M = Split(fso.OpenTextFile(Ini).ReadAll, vbCrLF)
T = fso.OpenTextFile(File).ReadAll
For i = 0 To UBound(M)
    R = Split(M(i), "=")  
    T = Replace(T, R(0), R(1))
Next
fso.CreateTextFile(File, True).Write T
Die Ersetzung wird "in der Datei" vorgenommen, es wird keine Sicherung erstellt. Unterstellt wird auch, dass es je Zeile in der Mapping-Datei nur ein einziges "=" (als Trennzeichen) gibt.

Grüße
bastla
Member: reinhr
reinhr Nov 09, 2009 at 21:27:56 (UTC)
Goto Top
Hallo Bastla,

nicht in der Mapping Datei sollen die Änderungen vorgenommen werden, sondern in der jeweilichen TXT, die immer wieder
automatisch durch ein System erstellt wird.
Ich kann diese TXT Datei jedoch so nicht verarbeiten. Deshalb benötige ich die BAT.
In der Mappingdatei steht nur die richtige Zuordnung.

Danke schon mal, das sieht ja schon mal gut aus!

Gruß
reinhr
Member: bastla
bastla Nov 09, 2009 at 21:37:19 (UTC)
Goto Top
Hallo reinhr!
nicht in der Mapping Datei sollen die Änderungen vorgenommen werden, sondern in der jeweilichen TXT
Anderes hatte ich weder angenommen noch gepostet ...

Grüße
bastla
Member: reinhr
reinhr Nov 09, 2009 at 22:08:08 (UTC)
Goto Top
Sorry bastla,

war mein Fehler!
Ich hab's mal ausprobiert, irgend was stimmt nicht.
Die Datei wird nicht geändert

Gruß
reinhr
Member: bastla
bastla Nov 09, 2009 at 22:31:24 (UTC)
Goto Top
Hallo reinhr!

Bei mir wird
xxxx|yyyy|1|4|1|7|zzzz
xxxx|yyyy|1|4|1|4|zzzz
xxxx|yyyy|1|4|1|6|zzzz
xxxx|yyyy|1|4|1|2|zzzz
xxxx|yyyy|1|4|1|0|zzzz
xxxx|yyyy|1|4|1|5|zzzz
xxxx|yyyy|1|4|1|3|zzzz
xxxx|yyyy|1|4|1|9|zzzz
xxxx|yyyy|1|4|1|1|zzzz
xxxx|yyyy|1|4|1|8|zzzz
mit
1|4|1|6=123456
1|4|1|5=234567
1|4|1|4=345600
zu
xxxx|yyyy|1|4|1|7|zzzz
xxxx|yyyy|345600|zzzz
xxxx|yyyy|123456|zzzz
xxxx|yyyy|1|4|1|2|zzzz
xxxx|yyyy|1|4|1|0|zzzz
xxxx|yyyy|234567|zzzz
xxxx|yyyy|1|4|1|3|zzzz
xxxx|yyyy|1|4|1|9|zzzz
xxxx|yyyy|1|4|1|1|zzzz
xxxx|yyyy|1|4|1|8|zzzz
Könnte es sein, dass die Ausgangsdatei bei Dir im Unicode-Format vorliegt? In diesem Fall wären folgende Zeile 6
T = fso.OpenTextFile(File, 1, False, True).ReadAll
bzw Zeile 11
fso.CreateTextFile(File, True, True).Write T
zu verwenden.

Soferne auch die "Mapping.ini" Unicode enthält, müsste Zeile 5 so aussehen:
M = Split(fso.OpenTextFile(Ini, 1, False, True).ReadAll, vbCrLF)

Grüße
bastla
Member: reinhr
reinhr Nov 09, 2009 at 22:50:25 (UTC)
Goto Top
Hallo bastla,

es will nicht klappen.
Was kann ich noch machen?

Gruß
reinhr
Member: bastla
bastla Nov 09, 2009 at 22:59:03 (UTC)
Goto Top
Hallo reinhr!
es will nicht klappen.
Auch nicht mit meinen Testdaten?
Was kann ich noch machen?
Was hast Du bisher bereits gemacht?

Grüße
bastla
Member: reinhr
reinhr Nov 09, 2009 at 23:08:07 (UTC)
Goto Top
Auf Laufwerk D befinden sich 3 Dateien

"Mapping.bat" mit dem Inhalt:
File = "D:\00001.txt"
Ini = "D:\Mapping.ini"
Set fso = CreateObject("Scripting.FileSystemObject")
M = Split(fso.OpenTextFile(Ini).ReadAll, vbCrLF)
T = fso.OpenTextFile(File).ReadAll
For i = 0 To UBound(M)
R = Split(M(i), "=")
T = Replace(T, R(0), R(1))
Next
fso.CreateTextFile(File, True).Write T

"0000.txt" mit dem Inhalt:
xxxx|yyyy|1|4|1|4|zzzz

"Mapping.ini" mit dem Inhalt:
1|4|1|6=123456
1|4|1|5=234567
1|4|1|4=345600

Wenn ich die Datei "Mapping.bat" ausführe blinkt kurz das DOS Fenster. Das wars.
Member: bastla
bastla Nov 09, 2009, updated at Oct 18, 2012 at 16:39:53 (UTC)
Goto Top
Hallo reinhr!

Ziemlich weit oben hatte ich eigentlich erwähnt, dass mein Entwurf ein VBScript ist - demzufolge bitte nicht als ".bat", sondern als ".vbs" speichern ...

Grüße
bastla
Member: reinhr
reinhr Nov 09, 2009 at 23:29:48 (UTC)
Goto Top
Du bist echt genial,bastla - jetzt hast du mir wieder richtig stark geholfen.
Ich danke dir!
Jetzt klappts!!!

Vielen Dank nochmal!

Ciao
reinhr
Member: reinhr
reinhr Nov 10, 2009 at 00:41:51 (UTC)
Goto Top
Hallo bastla,

es gibt noch ein Problem!
Wenn in der Mapping Datei z.B.

1|3|2|1=10983:6
1|3|2|16=10983:7

steht, und in der TXT steht XXX|YYY|1|3|2|16|zzz
dan wird 10983:6 ausgegeben.

Kannst Du das noch ändern.
Übrigens wäre es doch besser, wenn nur der NEUE Wert in der Datei stehen würde.
Also nur 10983:7

Gruß
reinhr
Member: reinhr
reinhr Nov 10, 2009 at 17:26:45 (UTC)
Goto Top
Hallo Bastla,

kannst du den Code so verändern, dass die Datei "00001.txt" sequenziell bearbeitet wird.
Es kann nämlich vorkommen, dass mehrere Dateien (00002.txt, 00003.txt) nacheinander im Verzeichnis erstellt werden,
aber die Erste Datei (00001.txt) nicht sofort weiter verarbeitet werden kann, da das externe Programm das die veränderte Datei verarbeitet noch nicht bereit ist.

Gruß
reinhr
Member: bastla
bastla Nov 10, 2009 at 20:10:55 (UTC)
Goto Top
Hallo reinhr!

Zunächst zur Korrektur der Ersetzung (durch das Ergänzen des Such-/Ersetzungsbegriffes um die Trennzeichen sollte das Teilstring-Problem "1|3|2|1" vs "1|3|2|16" gelöst sein):
File = "D:\00001.txt"  
Ini = "D:\Mapping.ini"  

Set fso = CreateObject("Scripting.FileSystemObject")  
M = Split(fso.OpenTextFile(Ini).ReadAll, vbCrLF)
T = fso.OpenTextFile(File).ReadAll
For i = 0 To UBound(M)
    R = Split(M(i), "=")  
    WScript.Echo R(0) & " --> " & R(1)  
    T = Replace(T, "|" & R(0) & "|", "|" & R(1) & "|")  
Next
fso.CreateTextFile(File, True).Write T
Was ich nicht verstanden habe, ist: Übrigens wäre es doch besser, wenn nur der NEUE Wert in der Datei stehen würde.

Du meinst damit ja wohl nicht, dass die gesamte Zeile durch zB "10983:7" ersetzt werden soll?
Auch die zusätzliche Anforderung der "sequenziellen" Verabeitung (und die Bedeutung der weiteren Dateien "00002.txt", etc) erschließt sich mir leider nicht - daher bitte eine ausführlichere Beschreibung dieses Problems ...

Grüße
bastla
Member: reinhr
reinhr Nov 10, 2009 at 21:16:44 (UTC)
Goto Top
Hallo Bastla,

Zu Deiner Frage - Ja, das meine ich mit "NEUE Zeile".

Der Wert "File = "D:\00001.txt" darf nicht konstant sein, da es vorkommen kann, dass sekundenweise mehrere TXT Dateien von einem externen Programm in D:\ geschrieben werden.
Die heissen dann 00002.txt, 00003.txt usw.

Gruß

reinhr
Member: bastla
bastla Nov 10, 2009 at 21:37:40 (UTC)
Goto Top
Hallo reinhr!

Um die gesamte Zeile zu ersetzen (und unter der Voraussetzung, dass jeder Suchbegriff nur einmal in der Datei vorkommen kann), könntest Du es mit folgender (ungetesteten) Version versuchen:
File = "D:\00001.txt"  
Ini = "D:\Mapping.ini"  

Set fso = CreateObject("Scripting.FileSystemObject")  
M = Split(fso.OpenTextFile(Ini).ReadAll, vbCrLF)
T = Split(fso.OpenTextFile(File).ReadAll, vbCrLF)
For i = 0 To UBound(M)
    R = Split(M(i), "=")  
    For j = 0 To UBound(T)
        If InStr(T(j), "|" & R(0) & "|") > 0 Then  
            T(j) = R(1)
            Exit For
        End If
    Next
Next
fso.CreateTextFile(File, True).Write Join(T, vbCrLF)
Um den Dateinamen variabel zu machen, kannst Du die Zeile 1 durch
File = WScript.Arguments(0)
ersetzen - es wird dann der Dateiname (mit Pfad) als Aufrufparameter erwartet. Per Batch ließe sich das Ganze dann etwa so steuern:
for /f "delims=" %%i in ('dir /b /a-d D:\000*.txt') do cscript //nologo D:\ReplaceScript.vbs "%%i"
Damit werden alle der Dateimaske "D:\000*.txt" entsprechenden Dateien zur Bearbeitung an das Script übergeben.

Grüße
bastla
Member: reinhr
reinhr Dec 02, 2009 at 13:27:38 (UTC)
Goto Top
Hallo Bastla,

der bisherige Code läuf sehr gut., Danke nochmal dafür!

Jetzt ist allerdings das Problem aufgetreten, dass doch hin und wieder *.TXT Dateien geschrieben werden,
die in der Mapping.ini nicht vorhanden sind.

Diese Dateien werden mit dem bisherigen Code auch nicht verändert.

Was muss am Code verändert werden , dass bei einer TXT Datei, bei der kein Mapping möglich ist ein alternativ Text geschrieben wird. Z.B. "War keine Mappinginfo vorhanden".
Noch besser wäre es, wenn es keine Mappinginformation gibt, soll die Datei gleich gelöscht werden.

Gruß
Roland
Member: bastla
bastla Dec 02, 2009 at 19:47:10 (UTC)
Goto Top
Hallo reinhr!

Etwa so:
File = WScript.Arguments(0)
Ini = "D:\Mapping.ini"  

Set fso = CreateObject("Scripting.FileSystemObject")  
M = Split(fso.OpenTextFile(Ini).ReadAll, vbCrLF)
T = Split(fso.OpenTextFile(File).ReadAll, vbCrLF)
OK = False

For i = 0 To UBound(M)
    R = Split(M(i), "=")  
    For j = 0 To UBound(T)
        If InStr(T(j), "|" & R(0) & "|") > 0 Then  
            T(j) = R(1)
            OK = True
            Exit For
        End If
    Next
Next

If OK Then
    fso.CreateTextFile(File, True).Write Join(T, vbCrLF)
Else
    fso.DeleteFile(File)
End If
Achtung - wenn keine Ersetzung vorgenommen werden konnte, wird die Datei kommentarlos (ohne Rückfrage) gelöscht.

Grüße
bastla