zeix450
Goto Top

Mittels VBS eine Zeile anhand Suchkriterien in .txt-Datei einfügen

Hallo Zusammen

Ich habe einige, wenige Erfahrungen mit VBS-Skripten, da wir diese bei uns zur Datenveredelung nutzen. Meistens kann ich ein bestehendes Skript umschreiben, aber zu nachfolgendem Problem gibt es leider keine passende Vorlage. Ich danke euch im Voraus für eure Hilfe.

Ausgangslage

Ich habe eine Datei "fplan.txt", diese wird bereits rege durch andere Skripts bearbeitet wird. Sie enthält Fahrtdaten. Eine Fahrt wird jeweils durch eine Zeile beginnend mit *Z begrenzt, siehe folgendes Beispiel:

*Z 09206 000011 101 % -- 6891308650 --
*I FD 8503000 8718206 000000 2032310 %
*G TGV 8503000 8718206 %
*A 02 8503000 8718206 %
*A VE 8503000 8500010 056276 %
*A VE 8500010 8718206 224767 %
*A GP 8500010 8718206 %
*A VN 8503000 8718206 %
*A WS 8503000 8718206 %
*EN 8500010 8718206 %
*R %
8503000 Zürich HB 00734 %
0000175 Hauenstein-Basistunn -00800 -00800 %
8500010 Basel SBB 00827 00834 %
8718206 Mulhouse Ville 00853 %
*Z 09210 000011 101 % -- 6891308650 --
etc.

Das Skript soll folgendes tun, auf bestimmten Fahrten, welche ich durch Nummern der Fahrten definiere (zu finden in der *Z-Zeile, Beispiel 9206, 9210, 9214, etc.) die Zeile *EN einfügen, wie sie auch im Beispiel zu sehen ist.

Problem

Die *EN Zeile soll zwischen Basel SBB und Mulhouse Ville gelten, dazu muss die Zeile *EN 8500010 8718206 % (das %-Zeichen ist nötig) eingefügt werden. Die Problematik besteht darin, dass auch die Gegenrichtung eine solche Zeile erhalten soll, da müsste sie aber folgendermaßen aussehen: *EN 8718206 8500010 %.

Sprich das Skript sollte folgende Schritte ausführen:

1. Nenne die Datei "fplan.txt" in "fplan.old" um und generiere eine neue Datei "fplan.txt" und schreibe dort rein
2. Suche in Datei fplan.txt nach den definierten Fahrten (in der Praxis führen wir hier jeweils eine Liste im .txt-Format, wo man die Nummern ergänzen oder löschen kann, das VBS-Skript greift dann auf diese Liste zu).
3. Finde heraus, in welche Richtung die Fahrt verkehrt (unabhängig vom Beispiel, da das Skript auch auf andere Bahnhöfe angewendet werden sollte)
4. Füge die *EN-Zeile anhand der für die Fahrten definierten Betriebspunkte ein (im Beispiel Basel und Mulhouse)
5. Lösche die Datei "fplan.old"

Ziel: in der neuen Datei "fplan.txt" sind alle Werte aus der ehemaligen Datei "fplan.old" enthalten plus die *EN-Zeile bei den definierten Fahrten.

Lösungsansatz

Ich habe versucht, das Skript für die Zeile *I FD um zu schreiben (auch diese Zeile findet ihr im obigen Beispiel) leider funktioniert dieses Skript grundlegend anders bzw. greift auf andere Suchkriterien zurück.

Kenn = "*Z"
Kenn2 = "*L"
P2Start = 10
P2Ende = 15
Kenn3 = "*G "
P1Start = 1
P1Ende = 3

P3Start = 8
P3Ende = 22
Entf = "0" 'zu entfernendes Zeichen am Beginn des Wertes für die Ausgabeliste
Einf = "*I FD "
EndSign = " %"
NStart = 2000000
Stellen = 7

With WScript.Arguments
If .Count <> 4 Then
WScript.Echo "Falsche Anzahl an Argumenten!"
WScript.Quit 1
Else
Ein = .Item(0)
Aus = .Item(1)
Liste = .Item(2)
AListe = .Item(3)
End If
End With

Nummer = 10 ^ Stellen + NStart 'Startwert (um eine Zehnerpotenz größer als lt "Stellen" wegen der führenden Nullen) erzeugen
KLen = Len(Kenn) 'Längen der Teilstrings vor der Schleife ...
P2Len = P2Ende - P2Start + 1 '...
P1Len = P1Ende - P1Start + 1
P3Len = P3Ende - P3Start + 1 '... und damit nur einmal berechnen
WertLen = Len(Wert)

Mark = "§§§" 'Platzhalter für einzufügende Zeile; darf in der zu verarbeitenden Datei nicht enthalten sein

Set fso = CreateObject("Scripting.FileSystemObject")
Set E = fso.OpenTextFile(Ein)
Set A = fso.CreateTextFile(Aus)
Set AL = fso.CreateTextFile(AListe)
Set IT = fso.OpenTextFile(AListe)

'Negativliste so in Variable einlesen, dass jeder Eintrag durch eine Zeilenschaltung begrenzt ist
L = vbNewline & fso.OpenTextFile(Liste).ReadAll & vbNewLine

Do While Not E.AtEndOfStream
Z = E.ReadLine
If Left(Z, KLen) = Kenn Then 'Blockbeginn
If Krit1 * Krit2 = 0 Then 'wenn beide Kriterien erfüllt sind ...
'... Block schreiben und dabei Zusatz-Zeile für Platzhalter (lt Var "Mark") einsetzen ...
A.Write Replace(Block, Mark, vbNewline & Einf & Zusatz & EndSign)
Gattung = 0
'Zeile mit Nummer und Wert aus Zeile "Krit1" in Ausgabeliste schreiben
AL.WriteLine Right(Nummer, Stellen) & " " & Wert
Else ' ... ansonsten ...
A.Write Replace(Block, Mark, "") '... Platzhalter vor dem Schreiben rückstandsfrei entfernen
Gattung = 0
End If
If Wert <> "" Then 'ab zweitem Block ...
'... neuen Block mit Zeilenschaltung (vorhergehender Block endet ohne Zeilenschaltung) beginnen
Block = vbNewLine & Z & Mark
Else
Block = Z & Mark
End If
Zugnummer = Mid(Z, 4, 5) 'Wert auslesen
Do While Left(Zugnummer, 1) = Entf 'Solange Wert mit Zeichen lt "Entf" beginnt ...
Zugnummer = Mid(Zugnummer, 2) '... erstes Zeichen von Wert abschneiden
Loop
If Zugnummer = Wert then
Wert = 0
Else
Nummer = Nummer + 1 'Nummer weiterzählen
End if
Wert = Zugnummer
'Teilstring in "L" (Liste) suchen und Ergebnis als 0 oder 1 speichern
Krit1 = Sgn(InStr(L, vbNewline & Mid(Z, P2Start, P2Len) & vbNewline))
Krit2 = 0 'zurücksetzten von Krit2
Else
Block = Block & vbNewline & Z 'Zeile an Block mit Zeilenschaltung anfügen
End If
If Left(Z, KLen) = Kenn2 Then Krit2 = 1 'auf 2. Kriterium ("*L") prüfen
'zusätzlichen Teilstring nach einem Leerzeichen an die Zusatzzeile anfügen
If Left(Z, P1Len) = Kenn3 Then
If Gattung = 0 then
Didok1 = Mid(Z, 8, 7)
Didok2 = Mid(Z, 16, 7)
Zusatz = Didok1 & " " & Didok2 & " 000000 " & Right(Nummer, Stellen)
Gattung = 1
Else
If Gattung = 1 then
Didok2 = Mid(Z, 16, 7)
Zusatz = Didok1 & " " & Didok2 & " 000000 " & Right(Nummer, Stellen)
Gattung = 2
Else
If Gattung = 2 then
Didok2 = Mid(Z, 16, 7)
Zusatz = Didok1 & " " & Didok2 & " 000000 " & Right(Nummer, Stellen)
Gattung = 0
Else
End If
End If
End If
Else
End If
Loop

'letzten Block verarbeiten
If Krit1 * Krit2 = 0 Then 'wenn beide Kriterien erfüllt sind ...
'... Block schreiben und dabei Zusatz-Zeile für Platzhalter (lt Var "Mark") einsetzen ...
A.Write Replace(Block, Mark, vbNewline & Einf & Zusatz & EndSign)
'Zeile mit Nummer und Wert aus Zeile "Krit1" in Ausgabeliste schreiben
AL.WriteLine Right(Nummer, Stellen) & " " & Wert
Else ' ... ansonsten ...
A.Write Replace(Block, Mark, "") '... Platzhalter vor dem Schreiben rückstandsfrei entfernen
End If

Danke, wenn hier jemand mehr weiss face-smile

Content-Key: 380727

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

Ausgedruckt am: 19.03.2024 um 07:03 Uhr

Mitglied: colinardo
colinardo 19.07.2018, aktualisiert am 20.07.2018 um 15:20:04 Uhr
Goto Top
Servus!
Leider fehlen hier viele Informationen die hier aber essentiell sind.
3. Finde heraus, in welche Richtung die Fahrt verkehrt (unabhängig vom Beispiel, da das Skript auch auf andere Bahnhöfe angewendet werden sollte)
Was soll hier als Referenz gelten? Die letzten zwei Zeilen vor einer neuen *Z Zeile??
4. Füge die *EN-Zeile anhand der für die Fahrten definierten Betriebspunkte ein (im Beispiel Basel und Mulhouse)
Definierte Betriebspunkte? D.h. Die immer die Nummern der letzten zwei Zeilen vor einer neuen *Z Zeile oder an welchen Details soll das fest gemacht werden?
Und eingefügt werden soll immer vor der Zeile mit *R %?

Ich würde dass ganze effektiver mit Powershell lösen, hier mal so wie ich deine etwas verkomplizierte Beschreibung interpretieren konnte:
# Datei mit Fahhrplan
$file = 'D:\fplan.txt'  
# Liste mit Nummern untereinander
$liste = 'D:\liste.txt'  
$search = gc $liste
$content = gc $file | out-string
$search | %{
    $content = $content -replace "(?ism)^(\*Z 0*($_).*?)^(\*R %.*?(^\d+)[^\r\n]+\s+(^\d+)[^\r\n]+)\s+(?=(^\*Z|\Z))",('$1*EN $4 $5 %' + "`r`n" +'$3')  
}
$content | sc $file

Hier meine bildliche Interpretation:

screenshot

Aus folgendem Beispiel
*Z 09206 000011 101 % -- 6891308650 --
*I FD 8503000 8718206 000000 2032310 %
*G TGV 8503000 8718206 %
*A 02 8503000 8718206 %
*A VE 8503000 8500010 056276 %
*A VE 8500010 8718206 224767 %
*A GP 8500010 8718206 %
*A VN 8503000 8718206 %
*A WS 8503000 8718206 %
*R %
8503000 Zürich HB 00734 %
0000175 Hauenstein-Basistunn -00800 -00800 %
8500010 Basel SBB 00827 00834 %
8718206 Mulhouse Ville 00853 %
*Z 09206 000011 101 % -- 6891308650 --
*I FD 8503000 8718206 000000 2032310 %
*G TGV 8503000 8718206 %
*A 02 8503000 8718206 %
*A VE 8503000 8500010 056276 %
*A VE 8500010 8718206 224767 %
*A GP 8500010 8718206 %
*A VN 8503000 8718206 %
*A WS 8503000 8718206 %
*R %
8503000 Zürich HB 00734 %
0000175 Hauenstein-Basistunn -00800 -00800 %
8718206 Mulhouse Ville 00853 %
8500010 Basel SBB 00827 00834 %
wird dann mit obigem Code
*Z 09206 000011 101 % -- 6891308650 --
*I FD 8503000 8718206 000000 2032310 %
*G TGV 8503000 8718206 %
*A 02 8503000 8718206 %
*A VE 8503000 8500010 056276 %
*A VE 8500010 8718206 224767 %
*A GP 8500010 8718206 %
*A VN 8503000 8718206 %
*A WS 8503000 8718206 %
*EN 8500010 8718206 %
*R %
8503000 Zürich HB 00734 %
0000175 Hauenstein-Basistunn -00800 -00800 %
8500010 Basel SBB 00827 00834 %
8718206 Mulhouse Ville 00853 %
*Z 09206 000011 101 % -- 6891308650 --
*I FD 8503000 8718206 000000 2032310 %
*G TGV 8503000 8718206 %
*A 02 8503000 8718206 %
*A VE 8503000 8500010 056276 %
*A VE 8500010 8718206 224767 %
*A GP 8500010 8718206 %
*A VN 8503000 8718206 %
*A WS 8503000 8718206 %
*EN 8718206 8500010 %
*R %
8503000 Zürich HB 00734 %
0000175 Hauenstein-Basistunn -00800 -00800 %
8718206 Mulhouse Ville 00853 %
8500010 Basel SBB 00827 00834 %
Grüße Uwe