Substring-Verarbeitung in Batch-Scripts
Hallo zusammen,
ich möchte aus einer Ascii-Datei den 1. Satz mit variablen Satz- und Feldlängen einlesen. Mein Problem dabei ist, dass es keine festen Feldlängen gibt und dass manche Felder optional sind.
Genauer:
- Der Satz gliedert sich in Blöcke, die jeweils mit einem Header ZAA, ZAB oder ZAC beginnen.
- Der Block ZAA ist optional, muss also nicht immer vorhanden sein (3. Bsp.).
- Der Block ZAB wird durch das Trennzeichen '+' in mehrere Segmente aufgegliedert.
- Der Block ZAC und evt. weitere sind uninteressant.
- Ein Segment (zwischen zwei '+'-Zeichen) kann aus 0 - 2 Feldern bestehen. Bei 2 Feldern
wird als Trennzeichen ein ':' benutzt.
- Frage: Wie weise ich die Felder Variablen zu?
1. Beispiel:
ZAA+001ZAB+ABC:1+4711:01+4721:05+060321:1021+123++1++ZAC+++...
2. Beispiel:
ZAA+002ZAB+DEF:2+4712:02+4722:06+060322:1022+456++++ZAC+++...
3. Beispiel:
ZAB+GHI:3+4713:03+4723:07+060323:1023+789++++ZAC+++...
Meine Kenntnisse über For-Schleifen, Delims und String-Verarbeitung reichen für diese
Fragestellung leider nicht aus. Hat jemand eine Idee?
Vielen Dank
Many
ich möchte aus einer Ascii-Datei den 1. Satz mit variablen Satz- und Feldlängen einlesen. Mein Problem dabei ist, dass es keine festen Feldlängen gibt und dass manche Felder optional sind.
Genauer:
- Der Satz gliedert sich in Blöcke, die jeweils mit einem Header ZAA, ZAB oder ZAC beginnen.
- Der Block ZAA ist optional, muss also nicht immer vorhanden sein (3. Bsp.).
- Der Block ZAB wird durch das Trennzeichen '+' in mehrere Segmente aufgegliedert.
- Der Block ZAC und evt. weitere sind uninteressant.
- Ein Segment (zwischen zwei '+'-Zeichen) kann aus 0 - 2 Feldern bestehen. Bei 2 Feldern
wird als Trennzeichen ein ':' benutzt.
- Frage: Wie weise ich die Felder Variablen zu?
1. Beispiel:
ZAA+001ZAB+ABC:1+4711:01+4721:05+060321:1021+123++1++ZAC+++...
2. Beispiel:
ZAA+002ZAB+DEF:2+4712:02+4722:06+060322:1022+456++++ZAC+++...
3. Beispiel:
ZAB+GHI:3+4713:03+4723:07+060323:1023+789++++ZAC+++...
Meine Kenntnisse über For-Schleifen, Delims und String-Verarbeitung reichen für diese
Fragestellung leider nicht aus. Hat jemand eine Idee?
Vielen Dank
Many
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 30395
Url: https://administrator.de/forum/substring-verarbeitung-in-batch-scripts-30395.html
Ausgedruckt am: 24.04.2025 um 04:04 Uhr
11 Kommentare
Neuester Kommentar
Moin many,
vielen Dank für die exakte und vollständige Beschreibung des Inputs *gg ...großes Lob von mir!
Ähhm... magst Du auch verraten, wie der Output/die Verarbeitung aussehen soll?
In Variablen speichern ist ja im Batch wie auch in "echten" Programmiersprachen eine vorübergehende Geschichte.
Wo sollen denn welche "Felder" welcher "Satzarten" hin? In neue Dateien geschrieben? Oder in irgendwelche Variablen ZAB_3A.....ZAB_5B oder wie ist der Plan?
Rückfragend
Biber
vielen Dank für die exakte und vollständige Beschreibung des Inputs *gg ...großes Lob von mir!
Ähhm... magst Du auch verraten, wie der Output/die Verarbeitung aussehen soll?
In Variablen speichern ist ja im Batch wie auch in "echten" Programmiersprachen eine vorübergehende Geschichte.
Wo sollen denn welche "Felder" welcher "Satzarten" hin? In neue Dateien geschrieben? Oder in irgendwelche Variablen ZAB_3A.....ZAB_5B oder wie ist der Plan?
Rückfragend
Biber
Na, Many,
dann fehlen noch folgende Randbedingungen, ehe wir uns leichtfertig auf Batch als geeignetes Werkzeug einschiessen:
- ist die worst case-Länge eines Satzes kurz genug, um sie in einem Batch verarbeiten zu können? Und die Tokenanzahl auch < 55?
Wenn z.B. die ZAA-Zeile auch mal 500 Zeichen lang werden kann, würde ich eher in VB/JScript anfangen als mit Batch.
- die zweite Restriktion: Wenn denn die Feldinhalte abhängig von Ihrer Position bestimmte Bedeutung haben (wenn ich Deinen 2. Post richtig deute), dann sollten und können auch die Variablennamen sprechend sein.
Beispiel:
wenn ZAA-Feld2==ABC = Absendername ->Variablenname ZAA_Absender
wenn ZAA-Feld3==4711 = Kunden-Nr ->Variablenname ZAA_Kunden-Nr
wenn ZAA-Feld4==060321 = Datum ->Variablenname ZAA_Datum
wenn ZAA-Feld5==1021 = ........ZAA_Uhrzeit etc.
..und diese Variablennamen und Feldreihenfolgen sollten natürlich in Strukturbeschreibungsdateien ZAAFields.txt, ZABFields.txt, ZACFields.txt abgelegt sein (also quasi ein Mini-Mini-Data-Dictionary, eine Feldbeschreibung)
Hat u.a. den Vorteil, das sich ggf. auch gezielt nur auf die Felder 1-3, 7 und 14 zugreifen kann, wenn ich nur die brauche.
Ansonsten ist das Zerlegen des Strings auch im Batch kein Hexenwerk...
$cmd$type ZAAtest.txt
ZAA+001ZAB+ABC:1+4711:01+4721:05+060321:1021+123++1++ZAC+++...
$cmd$for /f "delims=+ tokens=1-25" %a in (ZAAtest.txt) do @echo %a %b %c %d %e %f %g %h %i %j
ZAA 001ZAB ABC:1 4711:01 4721:05 060321:1021 123 1 ZAC ...
Die viele Rückfragerei nur, damit wir nicht in die falsche Richtung loslaufen...
Ich stufe aber erstmal den Beitrag runter von "Tutorial" auf "Beitrag" *gg
Gruß
Biber
dann fehlen noch folgende Randbedingungen, ehe wir uns leichtfertig auf Batch als geeignetes Werkzeug einschiessen:
- ist die worst case-Länge eines Satzes kurz genug, um sie in einem Batch verarbeiten zu können? Und die Tokenanzahl auch < 55?
Wenn z.B. die ZAA-Zeile auch mal 500 Zeichen lang werden kann, würde ich eher in VB/JScript anfangen als mit Batch.
- die zweite Restriktion: Wenn denn die Feldinhalte abhängig von Ihrer Position bestimmte Bedeutung haben (wenn ich Deinen 2. Post richtig deute), dann sollten und können auch die Variablennamen sprechend sein.
Beispiel:
wenn ZAA-Feld2==ABC = Absendername ->Variablenname ZAA_Absender
wenn ZAA-Feld3==4711 = Kunden-Nr ->Variablenname ZAA_Kunden-Nr
wenn ZAA-Feld4==060321 = Datum ->Variablenname ZAA_Datum
wenn ZAA-Feld5==1021 = ........ZAA_Uhrzeit etc.
..und diese Variablennamen und Feldreihenfolgen sollten natürlich in Strukturbeschreibungsdateien ZAAFields.txt, ZABFields.txt, ZACFields.txt abgelegt sein (also quasi ein Mini-Mini-Data-Dictionary, eine Feldbeschreibung)
Hat u.a. den Vorteil, das sich ggf. auch gezielt nur auf die Felder 1-3, 7 und 14 zugreifen kann, wenn ich nur die brauche.
Ansonsten ist das Zerlegen des Strings auch im Batch kein Hexenwerk...
$cmd$type ZAAtest.txt
ZAA+001ZAB+ABC:1+4711:01+4721:05+060321:1021+123++1++ZAC+++...
$cmd$for /f "delims=+ tokens=1-25" %a in (ZAAtest.txt) do @echo %a %b %c %d %e %f %g %h %i %j
ZAA 001ZAB ABC:1 4711:01 4721:05 060321:1021 123 1 ZAC ...
Die viele Rückfragerei nur, damit wir nicht in die falsche Richtung loslaufen...
Ich stufe aber erstmal den Beitrag runter von "Tutorial" auf "Beitrag" *gg
Gruß
Biber
Moin Many,
so in etwa sähe eine Skizze aus.
Ergebnis ist
Gruß
Biber
so in etwa sähe eine Skizze aus.
:: -------snipp ZAB-Split.bat
@echo off
:: aus der Textdatei alle Zeilen verwerten, die mit "ZAB" beginnen... nur ZAB-Satzart
Set "NeededVars=ZAB_1A ZAB_1B ZAB_2A ZAB_2B ZAB_3A ZAB_3B ZAB_3A ZAB_4B"
Set "NeededVars=%neededVars% ZAB_5A ZAB_5B ZAB_6A ZAB_6B ZAB_7A ZAB7_B ZAB_8A ZAB_8B"
FOR %%a in ( "%needevars%") do set "%%a="
:: Die nächsten ECHO Zeilen nur für DEBUG
Echo Dateiinhalt %1:
Type %1
Echo ---------
Echo gesplittete Zeile:
for /f "delims=" %%i in ('findstr /b "ZAB" %1') do echo %%i
:: Ende von die letzten ECHO-Zeilen nur für DEBUG
for /f "delims=" %%i in ('findstr /b "ZAB" %1') do call :ZABSplit %%i
set ZAB
goto :eof
:ZABSplit
If [%1]== goto :eof
Set Thisline=%1
Set thisline=%thisline:ZAC=}%
:: ich ersetze "ZAC" durch ein seltenes Zeichen, weil ich da abschneiden will
For /f "tokens=1 delims=}" %%i in ("%thisline%") do set "Thisline=%%i"
:: echo Thisline ohne ZAC+++-Block [%thisline%]
Set thisline=%thisline:++=+$+%
Set thisline=%thisline:++=+$+%
Set thisline=%thisline:++=+$+%
echo Thisline alle "++" durch "+$+"ersetzt [%thisline%]
For /f "tokens=2-9 Delims=+" %%a in ("%thisline%") do (
IF [%%a] NEQ IF [%%a] NEQ [$] for /f "delims=: tokens=1-2" %%i in (":%%a") do (
Set ZAB_1A=%%i & Set ZAB_1B=%%j)
IF [%%b] NEQ IF [%%b] NEQ [$] for /f "delims=: tokens=1-2" %%i in (":%%b") do (
Set ZAB_2A=%%i & Set ZAB_2B=%%j)
IF [%%c] NEQ IF [%%c] NEQ [$] for /f "delims=: tokens=1-2" %%i in (":%%d") do (
Set ZAB_3A=%%i & Set ZAB_3B=%%j)
IF [%%d] NEQ IF [%%d] NEQ [$] for /f "delims=: tokens=1-2" %%i in (":%%d") do (
Set ZAB_4A=%%i & Set ZAB_4B=%%j)
IF [%%e] NEQ IF [%%e] NEQ [$] for /f "delims=: tokens=1-2" %%i in (":%%e") do (
Set ZAB_5A=%%i & Set ZAB_5B=%%j)
IF [%%f] NEQ IF [%%f] NEQ [$] for /f "delims=: tokens=1-2" %%i in (":%%f") do (
Set ZAB_6A=%%i & Set ZAB_6B=%%j)
IF [%%g] NEQ IF [%%g] NEQ [$] for /f "delims=: tokens=1-2" %%i in (":%%g") do (
Set ZAB_7A=%%i & Set ZAB_7B=%%j)
IF [%%h] NEQ IF [%%h] NEQ [$] for /f "delims=: tokens=1-2" %%i in (":%%h") do (
Set ZAB_8A=%%i & Set ZAB_8B=%%j)
)
goto :eof
:: --snapp ZABSplit.bat
$cmd$zabsplit zaatest.txt
Dateiinhalt zaatest.txt:
;1. Beispiel...
ZAA+001ZAB+ABC:1+4711:01+4721:05+060321:1021+123++1++ZAC+++...
;2. Beispiel:
ZAA+002ZAB+DEF:2+4712:02+4722:06+060322:1022+456++++ZAC+++...
;3.Beispiel
ZAB+GHI:3+4713:03+4723:07+060323:1023+789++++ZAC+++...
; Ende testdatei
---------
gesplittete Zeile:
ZAB+GHI:3+4713:03+4723:07+060323:1023+789++++ZAC+++...
Thisline alle "++" durch "+$+"ersetzt [ZAB+GHI:3+4713:03+4723:07+060323:1023+789+$+$+$+]
ZAB_1A=GHI
ZAB_1B=3
ZAB_2A=4713
ZAB_2B=03
ZAB_3A=060323
ZAB_3B=1023
ZAB_4A=060323
ZAB_4B=1023
ZAB_5A=789
Gruß
Biber
Moin Many,
freut mich, wenn es Dir weiterhilft.
Zu Deinen Anmerkungen:
Zeile 04 und 06: Ja, sind Tippfehler.
Wobei diese %neededvars%-Lösch-Mimik nur nötig ist, solange die ganzen %ZAB_xx%-Variablen wie in dem Beispiel oben GLOBAL angelegt werden.
Normalerweise, wenn sie in dem gleichen Batch weiterverarbeitet werden, wie Du es ja eigentlich vorhast, gehört hinter die erste Zeile noch ein
@echo off & setlocal
...dann sind diese Zeilen überflüssig. Im jetzigen Zustand wäre das Problem, das ZAB_xx-Variablen noch gesetzt sein könnten, wenn Du den Batch erst über eine Datei Zaatest1.txt laufen lässt und danach über eine andere Datei Zaatest2.txt.
Zeile 12 und 14... ja, da habe ich etwas mit der Interpretation der Anforderung gekämpft. Ich hatte dann beschlossen, es so zu interpretieren, dass nur "Satzart ZAB", also Sätze, die mit "ZAB" beginnen, verarbeitet werden.
Aber, gute Nachricht: alle anderen Sätze (z.B. beginnend mit ZAA) können ja mit genau Deiner "Set thisline=%thisline:ZAB=+{%"-Strategie in Sätze umgewandelt werden, die der Batch händeln kann.
Unten die "tokens=2-9" statt "tokens=1-8" kamen bei mir halt so zustande, weil bei mir das Token 1 immer dem String "ZAB" enthält.
Zur Frage: "- Die zu analysierende Zeile ist immer die erste Zeile. Wie stelle ich das denn ein?" ..tja, wie beschrieben, ich nehme nur die "Satzart ZAB" - alles, was mit "ZAB" beginnt durch den "findstr /b 'ZAB'"-Befehl.
Die anderen "Satzarten", also beginnend mit "ZAA" oder "ZAC" würde ich entspechend mit 'findstr /b "ZAA"' oder 'findstr "ZAC"'-rausfiltern ODER
mit 'findstr "ZAB"' (ohne Parameter /b) oder 'Find ZAB' alle Zeilen rausfiltern, die einen ZAB-Block enthalten.
An dieser Stelle weiß ich allerdings nicht, welche ZAB-Blöcke denn die sind, die Du verarbeiten willst bzw. welche denn Priorität vor den Anderen haben.
Aber Du hast ja erst mal den Anfang und ich denke, die Anpassung bekommst Du auch weiter hin. Im Großen und Ganzen scheint es ja in die richtige Richtung zu gehen.
Grüße
Biber
freut mich, wenn es Dir weiterhilft.
Zu Deinen Anmerkungen:
Zeile 04 und 06: Ja, sind Tippfehler.
Wobei diese %neededvars%-Lösch-Mimik nur nötig ist, solange die ganzen %ZAB_xx%-Variablen wie in dem Beispiel oben GLOBAL angelegt werden.
Normalerweise, wenn sie in dem gleichen Batch weiterverarbeitet werden, wie Du es ja eigentlich vorhast, gehört hinter die erste Zeile noch ein
@echo off & setlocal
...dann sind diese Zeilen überflüssig. Im jetzigen Zustand wäre das Problem, das ZAB_xx-Variablen noch gesetzt sein könnten, wenn Du den Batch erst über eine Datei Zaatest1.txt laufen lässt und danach über eine andere Datei Zaatest2.txt.
Zeile 12 und 14... ja, da habe ich etwas mit der Interpretation der Anforderung gekämpft. Ich hatte dann beschlossen, es so zu interpretieren, dass nur "Satzart ZAB", also Sätze, die mit "ZAB" beginnen, verarbeitet werden.
Aber, gute Nachricht: alle anderen Sätze (z.B. beginnend mit ZAA) können ja mit genau Deiner "Set thisline=%thisline:ZAB=+{%"-Strategie in Sätze umgewandelt werden, die der Batch händeln kann.
Unten die "tokens=2-9" statt "tokens=1-8" kamen bei mir halt so zustande, weil bei mir das Token 1 immer dem String "ZAB" enthält.
Zur Frage: "- Die zu analysierende Zeile ist immer die erste Zeile. Wie stelle ich das denn ein?" ..tja, wie beschrieben, ich nehme nur die "Satzart ZAB" - alles, was mit "ZAB" beginnt durch den "findstr /b 'ZAB'"-Befehl.
Die anderen "Satzarten", also beginnend mit "ZAA" oder "ZAC" würde ich entspechend mit 'findstr /b "ZAA"' oder 'findstr "ZAC"'-rausfiltern ODER
mit 'findstr "ZAB"' (ohne Parameter /b) oder 'Find ZAB' alle Zeilen rausfiltern, die einen ZAB-Block enthalten.
An dieser Stelle weiß ich allerdings nicht, welche ZAB-Blöcke denn die sind, die Du verarbeiten willst bzw. welche denn Priorität vor den Anderen haben.
Aber Du hast ja erst mal den Anfang und ich denke, die Anpassung bekommst Du auch weiter hin. Im Großen und Ganzen scheint es ja in die richtige Richtung zu gehen.
Grüße
Biber