105. Pragmatische Einführung in die CSV-Bearbeitung mit Batch


Einleitung

Die Bearbeitung von CSV-Dateien ist für alle Batchschreiber eine Herausforderung, wobei sämtliche Aktionen mit einfachen Variationen eines For-Befehls möglich sind. Dieses Tutorial hat den Anspruch Ihnen Grundkenntnisse zu vermitteln, um halbwegs Tabellen und die Logik der Batchbearbeitung zu verstehen.

Der erste Teil der Abhandlung ist für Anfänger zugeschnitten. Für Fortgeschrittene als Befehlssammlung von For-Schleifen sind die Kapitel 2-3 mit einer Methode zur Zusammenführung von Tabellenreihen und Tabellen per se interessant. Der Kernpunkt mit lauffähigen Batches sind im Teil 3.

Tipp vom Sternenhimmelstuermer: Bevor Sie sich als Privatmann in der Dos-Welt zur Bearbeitung von Tabellen verlieren, lernen Sie lieber die Befehlssätze von Excel & Co. und vergeuden nicht kreative Energie. Das, was hier gezeigt wird, reicht in den meisten Fällen für Batchbearbeitung und gibt Ihnen ein wenig Übersicht, was so im Hintergrund abläuft und die Möglichkeit For-Befehle zu verstehen - und die können Sie wirklich überall zur Bearbeitung von Textdokumenten verwenden und sei es nur wegen einer mangelnden Alternative an Softwareprogrammen auf dem PC...

Inhaltsangabe
Grundbegriffe
    *.csv
    *.bat
Einführung in den For Befehl - von der Pike auf für Anfänger
    Bearbeitung von Dateiinhalten
Teil 3 - Fortgeschrittene
    zwei separate Reihen aus verschiedenen Dokumenten Verbinden
    an zwei Reihen eine Reihe aus einem anderen Dokument anfügen
    Tabellen aus zwei Dokumenten nebeneinander zusammenführen. (beinhaltet beide vorherigen Lösungen: leichteste Lösung)
Teil 4
allgemeines zu findstr & Tabellenbearbeitung - mehr Ausklang als Tipps für Anfänger und Fortgeschrittene.
Fazit

Grundbegriffe

*.CSV


Wenn Sie mit Excel eine Tabelle erstellt haben, dann können Sie diese im berühmten CSV-Format (Comma-separeted Values) speichern. Das kann mit dem einfachen Editor geöffnet werden. Sie können durch Änderung der Dateiendung daraus aus gerne einen Text machen.

Der Begriff CSV ist ein wenig irreführend. Daten oder Werte einer Zeile (primitiv von links nach Rechts sortierte Daten/Werte) werden durch einen sogenannten Separator getrennt: Gebräuchlich sind dabei Leerzeichen, Komma, Doppelpunkt und Semikolon. Der Separator muss also keineswegs ein Komma in einer csv sein...

Die Wahl des Seperators hängt ein wenig von den Daten, bzw. Werten einer Tabelle ab:

Beispiel

Manfred Sternenhimmelstuermer 26.07.1971

Bei einem Leerzeichen als Trenner wären das die drei Zellen einer Zeile Vorname, Nachname und Geburtsdatum.

Ändern wir einmal die Eingabe und bringen Vorname und Nachname in eine "Zelle":

Manfred  Sternenhimmelstuermer, 26.07.1971
wären also nur zwei Datensätze mit dem Separator Komma

Das ist Ihnen zu einfach? Hochmut kommt vor dem Fall! Der Sternenhimmelstuermer sah schon viele fehlerhafte Batches (zusammengefasste DOS-Befehle zur Stapelverarbeitung von Befehlen), die viel Unsinn produzierten, weil der falsche Separator verwendet wurde.

Excel selbst ist beim Export von Tabellen gut gerüstet: Bei Verwendung von Komma statt Semikolon als Trenner müssen Sie beim Eyport gleich die Spracheinstellungen ändern. Ansonsten können Sie aber  im Speichern unter Dialog im Dropdownmenü von Dateityp eine andere Auswahl treffen:

1. unter Text (Tabstopp-getrennt)  *.txt - Textdokument mit Tabstopps - können Sie durch Änderung der Dateiendung von TXT in CSV gerne konvertieren...

2.CSV (Trennzeichen-Getrennt) (*.csv) - Trennung mit Semikolon: Vorteil ?,ü,ä bleiben erhalten - also in der Regel ihr Format.

3. Text (MS-Dos) (*.txt): Für Hardliner ohne ß,ü,ä,ö...ziemlich armseelig...das sollte reichen...

In Zukunft werden wir uns mit Leerzeichen oder Semikolon herumschlagen...das ist auch die Kernfrage für Sie! Im Zweifel ist ein Semikolon die bessere Wahl...

Ansonsten spricht auch nichts dagegen den Separator mit einer einfachen Vorschleife auszutauschen: Das werden Sie später verstehen und ist nur eine Zeile in der Art:

For /F "tokens=1,2,3 delims= " %%i in (Leerzeichen.txt) do echo %%i;%%j>semikolon.txt


bei einer Tabelle mit zwei Reihen. Das wird hier noch nicht erklärt, nur eine kleine Vorausschau, wie Befehle aussehen werden...

Eine Tabelle zeichnet sich weiterhin dadurch aus, dass Sie aus mehreren Zeilen untereinander besteht, die dann von oben nach unten als Reihen bezeichnet werden. Der Sternenhimmelstuermer schrieb bereits eine Abhandlung über den Seriendruck in Excel, in der das ziemlich gut erklärt wird...

Also ist eine Tabelle eine Ansammlung von Daten/Werten, die in einer Zeile in Bezug zueinander stehen und in einer Reihe derselben Kategorie entsprechen - meistens mit einer Überschrift.

Für die Batchbearbeitung ist die Überschrift ohne Bedeutung und führt auch oft zu falschen Ergebnissen - Daher die oft gestellte Frage: Wie lösche ich die erste Zeile eines Textdokumentes? Die Antworten in deutschen Foren sind teilweise erstaunlich-:) Die beste Lösung finden Sie hier und mal die Aufforderung an unsere deutschen Foren den Befehl more zu verbreiten...

Vereinfacht reicht ein einfacher Befehl in der cmd: More +1 xyz.txt > keine_Ueberschrift.txt aus, um den Inhalt einer Tabelle um eine Zeile zu verkürzen...Hilfe zu dem Befehl gibt es in der cmd unter more /? und Returntaste...

Im übrigen stört die Überschrift nicht wirklich, wie Sie die beibehalten können, wird noch gezeigt.

Eine weitere beliebte Falle sind Sonderzeichen. In der Regel klappt das bei üblicher Verwendung. Der Sternenhimmelstuermer greift das dann an gegebener Stelle auf auf...

*.bat Batch

Wir müssen eine Batch erstellen, um mehrere Befehle an die CMD (Kommandozeile) zu übergeben:

Zur Erstellung einer Batch (*.bat) brauchen Sie nur bordeigene Mittel (Texteditor)

1. Als Voraussetzung müssen Sie sich bekannte Dateiendungen anzeigen lassen: beliebigen Ordner öffnen: Organisieren - Layout - Menüleiste auswählen. In der Menüleiste: Extras - Ordneroptionen - Reiterkarte Ansicht: Dort Häkchen entfernen bei: Erweiterungen bei bekannten Dateitypen ausblenden.

2. Nun auf dem Desktop oder in einem Ordner mit rechter Maustaste auf freie Fläche drücken und neu - Textdokument auswählen.

3. Neues Textdokument öffnen (linker Doppelmausklick) und den o. a. Code durch kopieren über die Zwischenablage einfügen

4. Danach schließen. Abfrage mit Speichern mit ja beantworten.

5. Danach beliebigen Namen für die neue.bat vergeben - nur die Endung .bat ist vorgeschrieben - z. B-  sortieren.bat, genial.bat...


Einführung in den For-Befehl


Teil 1 Bearbeitung von Dateiinhalten


Der wird in der Hilfe der CMD mit dem Befehl for /? so gut erklärt, dass er einige hundert unbeantwortete Nachfragen generiert...

Leider ist er auch in einer Doppelfunktion zu gebrauchen, nämlich kann mit kleinen Variationen entweder der Dateiname oder der Inhalt einer Textdatei nach Ihren Wünschen verarbeitet werden...
Nehmen wir mal aufbauend auf einer kleinen Tabelle mehrere Beispiele, um am Ablauf die Grundfuntkionen zu erläutern. Dazu erstellen wir ein Textdokument mit folgenden Inhalt, erstmal als Tabelle dargestellt:


   fx Eingabezeile

 A B C
D
1 Name Vorname Geburtsdatum
2 Meyer Manfred 20.02.1971
3 Miller Luise 03.03.1982
Ausschnit einer Exceltabelle: Wie Sie sehen können, bedient sich selbst Excel einer Durchnummerierung von Zeilen. Deshalb kann es Sinnvoll sein, dass Sie die Zahlen der Reihe einfach in  Ihrer Tabelle in einem CSV- Dokument in der ersten Reihe emulieren...


So schön übersichtlich ist das im Textdokument nicht. Da sieht die Tabelle nach Export in ein Textdokument oder von ihnen eingetragen so aus:

Inhalt der Datei probe.txt

Name Vorname Geburtsdatum
Meyer Manfred 20,02.1971
Miller Luise 03.03.1982

Unsere Separatoren sind unverkennbar Leerzeichen. Für den For-Befehl sieht die Tabelle aus Batchsicht (Verdopplung der Prozentzeichen in einer Batch) so aus:

Name der Datei  (%%i %%j %%k. %%~ni) oder einfach nur der Dateiname...

"Tokens=1" (%%i)   "delims= "   "Tokens= 2" (%%j)  "delims= "   "Tokens=3" (%%k)
"Tokens=1" (%%i)   "delims= "   "Tokens= 2" (%%j)  "delims= "   "Tokens=3" (%%k)
"Tokens=1" (%%i)   "delims= "   "Tokens= 2" (%%j)  "delims= "   "Tokens=3" (%%k)

Das ist jetzt nicht zu 100 % korrekt, aber zur Veranschaulichung geeignet...

Ein Tokens ist also immer ein "Zell-Wert bzw. -Daten jeder Zeile. Das Trennzeichen ist ein Delims. In jeder Zeile wird ab einem Buchstaben (a oder i) jeder Zelleninhalt adressiert. Jede Zeile hat dabei denselben Aufbau.

Der For Befehl im Grundaufbau:

Ganze Befehl Probe.txt:

For /F "tokens=1,2,3 delims= " %%i in (probe.txt) do echo %%i  %%j >>ergebnis.txt

Machen Sie es sich erstmal einfach und legen unsere Batch Probe.txt und eine Batch mit irgenden einen Namen wie Versuchs.bat in einen Ordner.


Der For-Befehl für den Inhalt der Datei fängt mit For /F an. /F ist dabei ein Schalter von vielen, den wir durchgängig verwenden werden, um an den Inhalt der Tabelle zu kommen.

Dann werden erstmal sämtliche Zeilen angesprochen mit den Parametern Tokens und Delims,schauen Sie sich die obige Tabelle an, wie der For-Befehl denkt:

For /F "tokens=1,2,3 delims= "

Bei Delims vergessen Sie bitte micht das Leerzeichen nach dem Gleichheitszeichen. Ansonsten hat das den unschönen Effekt, dass eine Zeile als Ganzes ein Delims ist, was durchaus gewollt sein kann...

Den Befehl Delims bräuchten Sie bei vielen Zeilen nicht - das wird meistens bei Leerzeichen richtig interpretiert und für Tokens würde ein * Stern als Wildcard reichen. Es gibt auch noch drei ander Parameter: skip eol und usebackq - lesen Sie mal die Windowshilfe durch...

Dann kommt ein %%i in einer Batch erstmal die Adressierung an den ersten Tokens.
Inhalt:

For /F "tokens=1,2,3 delims= " %%i in (probe.txt)

---

Das ist also der Ort, wo der For-Befehl akiv wird. Als nächstes kommt die Aufforderung etwas zu tun do mit einem nachfolgenden Befehl aus ihrem reichhaltigen DOS-Wortschatz. Bei Tabellenbearbeitung ist das meistens echo:

For /F "tokens=1,2,3 delims= " %%i in (probe.txt) do echo

Was als nächstes wiedergegeben (echo) wird, also ausgegeben wird, bestimmen Sie!
 
For /F "tokens=1,2,3 delims= " %%i in (probe.txt) do echo %%i wirft Ihnen also in diesem Fall: Name, Meyer und Müller untereinander aus. Warum denn nicht nur Name?  Der For-Befehl arbeitet jede Zeile nacheinander unbarmherzig ab  und schnappt sich den ersten tokens mit dem Namen %%i aus  jeder Zeile. Ist aber nur eine Zeile in einer  Tabelle, dann wird auch nur eine Zeile bearbeitet. Also sollten Sie tunlichst bemüht sein, eine Tabelle in  einzelne Zeilen zu zerlegen - dazu kommen wir später...

For /F "tokens=1,2,3 delims= " %%i in (probe.txt) do echo %%i  %%j >>ergebnis.txt

Das Ergebnis wird jetzt in die Datei ergebnis.txt geschrieben (>>). Das doppelte Ausgabezeichen ist zwingend notwendig, da nur ein > Ausgabezeichen in der ersten Zeile immer wieder den letzten Wert überschreiben würde: die Ausgabe wäre im Beispiel Miller Luise.



For /F "tokens=1,2,3 delims= " %%i in (probe.txt) do echo %%i  %%j >>ergebnis.txt wirft dementsprechend in die neue Datei ergebnis.txt aus:

Name Vorname
Meyer Manfred
Miller Luise

For /F "tokens=1,2,3 delims= " %%i  in (probe.txt) do echo %%i  %%j %%k dementsprechend die ursprüngliche Tabelle.

Name Vorname Geburtsdatum
Meyer Manfred 20,02.1971
Miller Luise 03.03.1982

Geben Sie das jetzt mal in eine probe.csv aus:


For /F "tokens=1,2,3 delims= " %%i in (probe.txt) do echo %%i  %%j %%k  >>probe.csv

Es wird also eine Datei mit Namen probe.csv automatisch erstellt.

Das Ausgabezeichen >>  muss wie gesagt verdoppelt werden, weil für jede Zeile drei Werte ausgegeben werden. Schreiben Sie nur ein > Zeichen so wird in jeder Zeile das alte Dokument mit dem Inhalt der neuen Zeile überschrieben, mit dem unschönen Ergebnis nur die letzte Zeile zu erhalten. Das nennt man destruktives überschreiben - kann gar nicht oft genug wiederholt werden - bleiben wir lieber beim ergänzenden Schreiben:

In der ersten Zeile steht:            Name (%%i) Vorname (%%j)  Geburtsdatum (%%k)

In der zweiten Zeile steht:          Meyer (%%i) Manfred (%%j)  20.02.1979  (%%k)

In der dritten Zeile steht:            Miller (%%i) Luise (%%j)  03.03.1982  (%%k)

Da Sie die Variablen austauschen oder wegfallen lassen können, sollten Sie nun ein wenig  allein experimentieren. 

For /F "tokens=1,2,3 delims= " %%i in (probe.txt) do echo %%i %%j %%k >>%%i.csv

Dieser Befehl würde drei Dateien mit je einer Zeile ausgeben:

Erste Datei:        Name.csv :   Name (%%i) Inhalt: Vorname (%%j) Geburtsdatum (%%k)
Zweite Datei:     Meyer.csvMeyer (%%i) Inhalt: Manfred (%%j) 20,02.1971 (%%k)
Dritte Datei:       Miller.csvMiller (%%i) Inhalt: Luise (%%j) 03.03.1982 (%%k)

In jeder Zeile wird %%i also der Name der Datei, die neu erstellt wird. Deshalb reicht auch ein > Zeichen, da jeweils andere Werte %%i sind.

Warum war dieses dem Sternenhimmelstuermer wichtig? Sie können eine CSV mit diesem simplen Trick in Zeilen zerlegen und dann jede Zeile für sich bearbeiten. Das ist dann quasi eine Tabelle für sich mit einer Zeile. Haben Sie eine Zeile mit Nummern, dann können Sie daraus schön durchnummerierte Dateinamen erstellen...

Noch ein paar Worte zum Befehl echo:

Sie können die Variablen selbstverständlich drehen, dazwischen Text einfügen und die Variablen in eine andere Reihenfolg bringen - alles, was im normalen Echo-Befehl erlaubt ist, gilt auch für den For - Befehl:
z. B.
For /F "tokens=1,2,3 delims= " %%i in (probe.txt) do echo %%k  %%i  >>probe.csv
For /F "tokens=1,2,3 delims= " %%i in (probe.txt) do echo Guten_Tag Herr_ %%i  >>probe.csv

Die Anzahl der Tokens bleibt immer gleich, egal, was Sie selektieren. Denken Sie nur daran, dass jedes Wort mit Leerzeichen die Tabellenstruktur verändert.


Keine Rosen ohne Dornen: Sonderzeichen sind außerhalb eines Tokens möglich, aber nur mit einem  ^ Zeichen z. B. bei > also so in der Art: For /F "tokens=1,2,3 delims=" %%i in (probe.txt) do echo Guten Tag Herr ^>  %%i  >>probe.csv
ü,ä,ö können Sie bei Dateiinhalten durch den vorherigen Befehl chcp 28591 > NUL verwenden also:

chcp 28591 > NUL
For /F "tokens=1,2,3 delims=" %%i in (probe.txt) do echo Guten Tag Herr ^>  %%i  und schöne Grüße >>probe.csv

Das gilt also für die ü,ö,ä und Sonderzeichen außerhalb eines Tokens. Innerhalb von %%i und Co ist das wiederum kein Problem...

Das klappt meistens auch so, wenn nicht, dann diese Variante ausprobieren...

Für den Dateinamen auf DOS-Ebene ist das wiederum ein Problem. Da stört jedes Sonderzeichen ü,ö oder ? erheblich - ein spezielles deutsches Problem...

Anfänger bitte nicht verschreckt sein. Ihr habt jetzt schon in einem Durchgang so viel gelernt, dass Ihr nun problemlos Tabellen umgestalten, Reihen reduzieren, Tabellen konvertieren, und die Tabellen in  einzelne Zeilen zerlegen könnt. An dieser Stelle empfiehlt der Sternenhimmelstuermer auch einen Break. Das war tierisch viel Stoff und der nächste Teil wird eine Herausforderung...




Teil 2 Grundlagen for Befehl Kommandos

Als nächstes beschäftigen wir uns mit dem verschieben von Dateiinhalten  - keine Sorge, wir bleiben bei den Grundlagen. Die nächsten Zeilen sind dann der Einstieg in die effektive Bearbeitung. Der Sternenhimmelstuermer stellt hier eine Methode aus einem Guss vor, der von den vielen gut gemeinten Einzellösungen abweicht. Sie werden danach eine Tabelle komplett beherrschen - das mit wenig Befehlen und viel Fantasie...

Wir zerlegten ja gerade die Tabelle in Einzelteile, nun fügen wir diese wieder zusammen. Das wäre der letzte Arbeitsschritt, aber wir greifen da ein wenig vor:

Mit der oben vorgestellten  Zeile For /F "tokens=1,2,3 delims=" %% in (probe.txt) do echo %%i  %%j %%k >%%i.csv zerlegten wir eine Tabelle Namens probe.txt in drei einzelne *.csv - Dateien.

Erste Datei:        Name.csv :   Name (%%i) Inhalt: Vorname (%%j) Geburtsdatum (%%k)
Zweite Datei:     Meyer.csvMeyer (%%i) Inhalt: Manfred (%%j) 20,02.1971 (%%k)
Dritte Datei:       Miller.csvMiller (%%i) Inhalt: Luise (%%j) 03.03.1982 (%%k)

Mit dem Befehl

for /f "TOKENS=*" %%a in ('dir *.csv /b') do type "%%a" >> ergebnis.txt


fügen wir die Tabelle wieder zusammen. Wie Sie unschwer erkennen können ist die Sortierung der Zeilen im ergebnis.txt willkürlich. Um das zu demonstrieren, ließ der Sternenhimmelstuermer die Überschrift drin. Das werden wir im folgenden korregieren...

Nun zum Befehl: 

for /f "TOKENS=*" ist im Prinzip nichts neues, der Sternenhimmelstuermer verwendete eine Wildcard, also einen Stern für eine unbegrenzte Anzahl von Tokens. Delims wurden ausgelassen. Sind eh nur Leerzeichen und der For - Befehl interpretiert die meistens richtig...

%%a in ('dir *.csv /b') do type "%%a" >> ergebnis.txt 

Wir arbeiten alle *.csv-Dateien ab, in dem wir mit dem Dir mit Parameter /b - Befehl alle Namen der Dateien mit der Dateiendung CSV auswählen. Der Inhalt der Dateien sind alle Tokens. Die lassen wir mit einem Tippbefehl (Type) in den Ergebnistext (ergebnis.txt) ausdrucken. Nehmen Sie die Zeile einfach so hin und kopieren Sie sie...

Warum wurde jetzt das Ende erklärt? Der Sternenhimmelstuermer zerlegt grundsätzlich Tabellen in Einzelteile und bearbeitet diese dann. Dann können Sie z. B. leicht suchen und ersetzen:
Dazu machen wir erstmal einen Zwischenschritt und gehen wieder zum Anfang zurück. Diesmal werden wir die Daten in die Ausgangssortierung zurückbringen - samt Überschrift:

Wir haben die Datei probe.txt :

Name Vorname Geburtsdatum
Meyer Manfred 20,02.1971
Miller Luise 03.03.1982

und nummerieren diese erstmal durch:

FOR /F "tokens=*" %%A IN ('findstr /N .* "probe.txt"') DO echo %%A>> zahl.log

Damit haben wir mit dem Befehl findstr. und dem Parameter /N Jeder Zeile eine Nummer verpasst.  Jede Zeile ist durch den Stern des Tokens eine Zeile ohne Delims. %%A ist die Zeile, die vom Befehl findstr. in Probe.txt gefunden und nummeriert wird
Ausgegeben wird das ganze in einer Log-Datei, die der Sternenhimmelstuermer beim Verschiebespiel gerne benutzt. Die enden dann meistens nach getaner Arbeit mit einem del *.log - Befehl, der sämtliche Log-Dateien löscht.

Wir haben nun als Ergebnis in Zahl.log:

1:Name Vorname Geburtsdatum
2:Meyer Manfred 20,02.1971
3:Miller Luise 03.03.1982

Das ist doch schon mal Klasse. Wir haben also drei Tokens mit Leerzeichen und zwei Tokens durch einen Doppelpunkt getrennt. Jetzt brauchen wir nur noch die Zahl als Dateinamen in einem neuen Textdokument zu deklarieren und haben drei durchnummerierte Dateien. Deshalb fügen wir den folgenden Befehl als nächste Zeile der Batch ein oder Schreiben nun eine neue Batch mit folgenden Inhalt:

 
FOR /F "tokens=1,2* delims=: "  %%i  IN (zahl.log) DO echo %%j %%k  >zahl_%%i.log

Die cmd reagiert mit der Ausgabe von drei Dateien mit Zahl_1.log bis Zahl_3.log mit den entsprechenden drei Tokens

Zahl_1.log                                       Zahl_2.log                                 Zahl_3.log
Name Vorname Geburtsdatum       Meyer Manfred 20,02.1971       Miller Luise 03.03.1982

Warum? Das Delims des Doppelpunktes  sind zwei tokens  - die beiden Bestandteile.  Der Tokens  %%i ist die Zahl vor dem Doppelpunkt. %%j und %%k sind die folgenden delims nach dem Doppelpunkt der Leerzeichen. Ja, %%i ist ein halber Token nach dem Doppelpunkt und muss deshalb nicht erwähnt werden. Das ist etwas irretierend - nehmen Sie es einfach so hin...oder schreiben den Befehl in eine Versändliche Form um:

FOR /F "tokens=1,2 delims=:"  %%i  IN (rowone.log) DO echo %%j >zahl_%%i.log

Der Delims ist ein Doppelpunkt %%i ist das vor dem Doppelpunkt und %%j der zweite Delims - die Leerzeichen spielen keine Rolle

-----


Der Vorteil des Dateinamens ist nun, dass Sie die Zeilen halbwegs korrekt beim Zusammenfügen sortieren können. Dazu muss die Datei um mehrere Zeilen ergänzt werden. Fangen wir noch Mal von vorn an, um die Durchläufe zu beschreiben:

Jetzt löschen Sie bitte Alle Dokumente außer probe.txt
mit Inhalt:

Name Vorname Geburtsdatum
Meyer Manfred 20,02.1971
Miller Luise 03.03.1982

Dann erstellen Sie im selben Ordner eine.bat mit folgenden Inhalt:

FOR /F "tokens=*" %%A IN ('findstr /N .* "probe.txt"') DO echo %%A>> zahl.log
FOR /F "tokens=1,2* delims=: "  %%i  IN (zahl.log) DO echo %%j %%k  >zahl_%%i.log
set /a x=1
:weiter
for /f "TOKENS=*" %%a in ('dir zahl_%x%.log /b') do type "%%a" >> ergebnis.txt
set /a x=%x%+1
if exist zahl_%x%.log (goto weiter) else goto endspurt
:endspurt
end

Sie haben nun die beiden ersten Befehle gerade im Artikel ausführlich beschrieben bekommen. Das ist nun ein kompletter Durchlauf :

Erster Schritt: Die Zeilen unserer Probetabelle wurden mit findstr, nummeriert und in eine Logdatei geschrieben.

Zweiter Schritt: Die Nummern der Zeilen werden zu Überschriften einzelner Zeilendateien mit einer Zeile Inhalt.

Dritter Schritt: der wird jetzt erklärt. Im Prinzip ist das nun das Ende, nachdem Sie irgendwelche Aktionen durchgeführt haben:
Die einzelnen Dateien werden nun wieder in der richtigen Reihenfolge zusammengesetzt.

set /a x=1

Dazu setzen mit set /a eine Zahlenvariabel auf 1. Der Doppelpunkt mit :weiter ist ein Marker für eine Schleife.

for /f "TOKENS=*" %%a in ('dir zahl_%x%.log /b') do type "%%a" >> ergebnis.txt


hatten wir bereits in einer Abwandlung: Wir suchen nun alle Dateien, die Zahl_1.log heißen (x war ja gleich 1 im ersten Durchlauf) - wir wissen ja, dass es bei der Durchnummerierung auch eine 1 geben muss. Der Inhalt dieser Datei wird wieder in eine Datei Namens Ergebnis.txt geschrieben. Also wird dementsprechend die Überschrift in der ersten Zeile übernommen.

set /a x=%x%+1Danach erhöhen wir die Zahl um 1, was im ersten Durchlauf 2 macht.

if exist zahl_%x%.log (goto weiter) else goto endspurt
Wir prüfen nun, ob es eine Datei zahl_2.log gibt. Existiert die, geht es wieder zur Sprungmarke vor dem For Befehl, ansonsten (else) verlassen wir die Schleife und gehen zum Dateiende.

Diese Konstruktion ist nur möglich, weil wir wissen, dass in jeder Datei eine Zahl vorhanden ist. Normalerweise ist das verwenden von Variablen in For-Befehlen schwer. Das geht jetzt schon ziemlich in den Profibereich.



Teil 3


zwei separate Reihen aus verschiedenen Dokumenten Verbinden

Nach diesem ganzen Vorspiel geht es nun zur Sache und der Sternenhimmelstuermer sieht jetzt eine Chance, dass ihm noch ein paar Leser folgen können. Wir werden nun nämlich Reihen einer Tabelle Zusammenfügen und das nur mit einfachen Befehlen: Das ist jetzt auch für Fortgeschrittene:

YinYang.batch

FOR /F "tokens=1" %%A IN ('findstr /N .* "rowone.txt"') DO echo %%A>> Yin.log
FOR /F "tokens=1" %%A IN ('findstr /N .* "rowtwo.txt"') DO echo %%A>> Yang.log
FOR /F "tokens=1,2* delims=: "  %%i  IN (Yin.log) DO echo %%j >Yin_%%i.log
FOR /F "tokens=1,2* delims=: "  %%i  IN (Yang.log) DO echo %%j >Yang_%%i.log
set /a x=1
:weiter
for /f %%a in (Yin_%x%.log) do for /f %%i in (Yang_%x%.log) do echo %%a %%i >rownew_%x%.log
set /a x=%x%+1
if exist *_%x%.log (goto weiter) else goto endspurt
:endspurt
set /a y=1
:letzte
for /f "TOKENS=*" %%a in ('dir rownew_%y%.log /b') do type "%%a" >> ergebnis.txt
set /a y=%y%+1
if exist rownew_%y%.log (goto letzte) else goto ende
:ende
del *.log


Mit dieser kleinen Batch fügen Sie zwei Reihen aus verschiedenen Textdokumenten zusammen. Die Erklärung erfolgt nur im Schnelldurchlauf, da alle Bestandsteile im Laufe dieser Abhandlung bereits erklärt wurden.

Wir haben also zwei Datenreihen in den Dokumenten rowone.txt und rowtwo.txt, dieses sind die englischen Bezeichnungen für das internationale Publikum auf dieser Seite -:)

Voraussetzung ist, dass die Reihen gleich lang sind - z. B. Namen und Passwörter.

In den ersten beiden Reihen werden nun die Zeilen durchnummeriert mit einem Doppelpunkt. Die Befehle mit findstr hatten wir bereits erklärt.

Auch die Befehle drei und vier sind nicht neu. Es wird jeweils für eine Reihe ein Dokument mit einer Buchstaben-Zahlenkombination erstellt, diesmal als Log-Datei. Das ist durchaus in der Batchbearbeitung üblich.
Wir haben also soviel durchnummerierte Logdateien wie Zeilen in den Dokumenten. Ab jetzt wird wieder genauer erklärt - wer bishierher nur Bahnhof verstand, ab in Teil 2:

Sie sehen, wir setzen wieder x=1, um eine Schleife zu verwenden, um die einzelnen Zeilen-Log-Dateien nun zusammenzufügen.
: weiter ist wieder der Sprungpunkt für einen einfachen goto-Bfehl.

for /f %%a in (Yin_%x%.log) do for /f %%i in (Yang_%x%.log) do echo %%a %%i >rownew_%x%.log


Das ist nun der eigentlich neue Kern, den der Sternenhimmelstuermer vorstellen wollte - zwei ineinander verschachtelte For-Befehle. Die Syntax ist genau wieder dieselbe:

for /f %%a in (Yin_%x%.log) do


Bis hierher ist alles beim Alten. Im ersten Yin_1.log (x wurde beim ersten Durchlauf auf eins gesetzt), wird also %%a (Der eine Wert oder Datenbestandteil) angesprochen. Wir wissen, dass in dem Zeilendokument nur ein Wert steht. Das folgende geht auch nur mit einer Zeile. Warum? Sind mehrere Zeilen in einem Dokument, so würde der dumme For-Befehl nun alle Zeilen durchlaufen und das folgend mit allen Werten des nächsten For-Befehls. Das wollen wir nicht - mal erstmal die zweite Hälfte des Befehls erklären, dann werden Sie verstehen: for /f %%i in (Yang_%x%.log) do echo %%a %%i >rownew_%x%.log

Hier wird %%i im zweiten Zeilendokument angesprochen. Genau dasselbe wie im ersten Teil des Befehls Yin_%x%.log und Yang_%x%.log mit dem X-Wert : 1 werden also angesprochen. do echo %%a %%i >rownew_%x%.log ist nun die Ausgabe der beiden Datenwerte in ein Zwischendokument, was nun im ersten Durchlauf row_1.log heißt.

Da drin stehen nun unsere ersten beiden Werte der beiden Reihen. Würden nun mehrere Zeilen im Dokument stehen, so würde folgendes passieren:

Ausgangsdokumente:
log1      log2
Zeile1   Zeile3
Zeile2   Zeile4

Ausgabe
log1
Zeile1 Zeile3
log2
Zeile1 Zeile4
log3
Zeile2 Zeile3
log4
Zeile2 Zeile4

Richtig, alle Möglichkeiten werden miteinander ausgegeben. Bei drei Zeilen würde dieses dann neun Dokumente ergeben. Bei einer Zeile gibt es nur eine Paarungsmöglichkeit - das ist der Trick bei For For. Sie müssen immer mit einer Zeile arbeiten, weil Sie ansonsten zu viele unsinnige Dokumente bekommen.

Die nächsten Zeilen sind dann wieder wie bereits weiter oben erklärt. X wird um einen Wert erhöht. Es wird geprüft, ob (if) ein *_%x%.log, also ein Yin_2.log oder Yang _2.log vorliegt (x wurde ja in diesem Durchlauf auf zwei erhöht. Liegen die Dokumente vor, so geht es zur nächsten Teilenbearbeitung zurück zum Sprungpunkt weiter, ansonsten geht es zum endspurt...

:endspurt
set /a y=1
:letzte
for /f "TOKENS=*" %%a in ('dir rownew_%y%.log /b') do type "%%a" >> ergebnis.txt
set /a y=%y%+1
if exist rownew_%y%.log (goto letzte) else goto ende
:ende
del *.log


Im Endspurt wird wieder die Reihenfolge des Zusammensetzens berücksichtigt. Statt x nehmen wir y. Das ist so ziemlich egal. Im Ergebnistext wird ein rownew-y.log nach dem anderen zusammengesetzt und damit bleibt die ursprüngliche Reihenfolge gewahrt...
Am Ende werden die ganzen Logs gelöscht - eigentlich ziemlich einfach und alles Grundbefehle.


an zwei Reihen eine Reihe aus einem anderen Dokument anfügen


Mit zwei Reihen in in rowone.txt und einer Reihe in rowto.txt sähe das so aus:

FOR /F "tokens=1,2" %%A IN ('findstr /N .* "rowone.txt"') DO echo %%A %%B>> Yin.log
FOR /F "tokens=1" %%A IN ('findstr /N .* "rowtwo.txt"') DO echo %%A>> Yang.log
FOR /F "tokens=1,2,3* delims=:"  %%i  IN (Yin.log) DO echo %%j %%k >Yin_%%i.log
FOR /F "tokens=1,2* delims=:"  %%i  IN (Yang.log) DO echo %%j >Yang_%%i.log
set /a x=1
:weiter
for /f "delims=" %%a in (Yin_%x%.log) do for /f "delims=" %%i in (Yang_%x%.log) do echo %%i%%a >rownew_%x%.log
set /a x=%x%+1
if exist *_%x%.log (goto weiter) else goto endspurt
:endspurt
set /a y=1
:letzte
for /f "TOKENS=*" %%a in ('dir rownew_%y%.log /b') do type "%%a" >> ergebnis.txt
set /a y=%y%+1
if exist rownew_%y%.log (goto letzte) else goto ende
:ende
del *.log




Im Rowone.txt stehen also zwei Tokens mit dem Separator Leerzeichen. Im rowtwo.txt eine Reihe mit Datenwerten. Sie sehen, mit jeder neuen Reihe wächst die Batch, aber das Grundprinzip bleibt. Dabei sind die Nuancen das Wichtigste - ein Punkkt irgendwo zuviel oder zu wenig und das Ganze kippt. Grundlegend sind die tokens und Delims. Die sollten Sie nun eigentlich beherschen.



Tabellen aus zwei Dokumenten nebeneinander zusammenführen. (beinhaltet beide vorherigen Lösungen)


Das Zusammenführen untereinander ist langweilig. Mit der folgenden Batch können Sie beliebig viele Reihen beinhaltene Tabellen nebeneinander Zusammenfügen. Einzige Voraussetzung ist, das die Tabellenreihen gleich lang sind. Ist eigentlich nur eine Variation der beiden o. a. Batches für Reihen. Wieviel Werte in den Tabellen stehen, ist egal, aber es wäre für die spätere Bearbeitung unsinnig in die Breite zu gehen...Warum wurden dann die einzelnen Reihen erklärt? Um ein wenig Variationsbreite zu erlernen - das Leichte kommt jetzt:


Tabellen.bat


FOR /F "tokens=*" %%A IN ('findstr /N .* "tableone.txt"') DO echo %%A^: >> tableone.log
FOR /F "tokens=*" %%A IN ('findstr /N .* "tabletwo.txt"') DO echo %%A^: >> tabletwo.log
FOR /F "tokens=1,* delims=:"  %%i  IN (tableone.log) DO echo %%j  >tableone_%%i.log
FOR /F "tokens=1,* delims=:"  %%i  IN (tabletwo.log) DO echo %%j  >tabletwo_%%i.log
set /a x=1
:further
for /f "delims=" %%a in (tableone_%x%.log) do for /f "delims=" %%i in (tabletwo_%x%.log) do echo %%i%%a >tablenew_%x%.log
set /a x=%x%+1
if exist *_%x%.log (goto further) else goto final
:final
set /a y=1
:last
for /f "TOKENS=*" %%a in ('dir tablenew_%y%.log /b') do type "%%a" >> result.txt
set /a y=%y%+1
if exist tablenew_%y%.log (goto last) else goto nowend
:nowend
FOR /F "tokens=1,2 delims=:"  %%i  IN (result.txt) DO echo %%i%%j >>resulttwo.txt
del *.log


Ach ja, es wurden englische Begriffe verwendet, damit die Batch international ist. Es gab für diese Datei keine englischen Vorbilder: die Sternenhimmelstuermerseite setzt auf der Metaebene Impulse...

Voraussetzung sind die Dokumente tableone.txt und tabletwo.txt im gleichen Verzeichnis. Der Name der Batch ist egal.bat.

Beispiel:

tableone.txt
Name Vorname Geburtsdatum
Meyer Uli 10.10.1973

tabletwo.txt
Adresse Plz
Berlin 10000

Die sind nur zur Demonstration so mickrig - Es ist egal, wieviele Zeilen da stehen oder Reihen...

Was macht die Batch?

FOR /F "tokens=*" %%A IN ('findstr /N .* "tableone.txt"') DO echo %%A^: >> tableone.log
FOR /F "tokens=*" %%A IN ('findstr /N .* "tabletwo.txt"') DO echo %%A^: >> tabletwo.log

Die beiden Zeilen der Dokumente werden jeweils durchnummeriert und in zwei Log-Dateien ausgegeben. Am Ende jeder Zeile wird hinter der Ausgabe der Zeile ein Doppelpunkt (^:  Das Zeichen ^  wieder zur Ausgabe des Doppelpunktes...) angefügt
So ein tableone.log könnte nun wie folgend beschrieben aussehen:

1:Name Vorname Geburtsdatum:
2:Meyer Uli 10.10.1973:

In dem anderen Dokument (tabletwo.txt) passiert dasselbe:

1:Adresse Plz:

2:Berlin 10000:

FOR /F "tokens=1,* delims=:"  %%i  IN (tableone.log) DO echo %%j  >tableone_%%i.log
FOR /F "tokens=1,* delims=:"  %%i  IN (tabletwo.log) DO echo %%j  >tabletwo_%%i.log

Sie sehen nun den Sinn der Aktion mit den Doppelpunkten. Egal, wieviel Werte in einer Zeile nebeneinander sind, es gibt zwei Tokens durch den Delims Doppelpunkt getrennt. Der Vorteil: Sie brauchen sich nur noch den Tokens %%j ins neue Dokument ausgeben lassen. Dieser umfasst alle Daten bzw. Werte mit Leerzeichen, die zwischen den Doppelpunkten stehen.

Der erste Tokens %%i geht in die Überschrift als Zahl in das tableone_%%i.log. tokens=1,* sind praktisch nur zur Unterstützung, das i und j richtig erkannt werden...Seperator ist der Doppelpunkt.

Beispiel:

tableone_1.log                                    tableone_2.log                            tabletwo_1.log     tabletwo_2.log
Name Vorname Geburtsdatum:             Meyer Uli 10.10.1973:             Adresse Plz:          Berlin 10000:

set /a x=1
:further

Jetzt setzen wir wieder eine Variable x auf 1 und setzen danach einen Sprungpunkt.

for /f "delims=" %%a in (tableone_%x%.log) do for /f "delims=" %%i in (tabletwo_%x%.log) do echo %%i%%a >tablenew_%x%.log

Das war bei den Reihenbatches bereits unsere Standard-zusammenfüg -Zeile. Klappt wie in vorherigen Beispielen bewiesen nur mit einzeiligen Dokumenten - deshalb hatten wir vorher die Tabellen in Zeilen zerlegt. Sind wieder zwei For Befehle. Jeder für ein Log-Dokument - hier wird zusammengeführt, was zusammengehört: im ersten Durchlauf ist x auf 1 gesetzt. Aso werden die ersten Zeilen von tableone_1.log und table_1.log zusammengesetzt:

In tablenew_1.log wird das zusammengeführt: Name Vorname Geburtsdatum:   Adresse Plz:

Die Doppelpunkte sind noch eine Altlast und werden erstmal mitgeschleppt...

set /a x=%x%+1

X wird erstmal auf 2 gesetzt...

if exist *_%x%.log (goto further) else goto final

Das wird jetzt wichtig, denn mit dem if exist - Befehl wird abgefragt, ob noch eine tableone_2.log vorliegt. Der Stern ist eine Wildcard - eigentlich wird nur nach einer Datei mit x=2 abgefragt. Die liegt ja auch wirklich in unserem Beispiel vor, also geht es in die nächste Runde (mit goto zum vorherigen Sprungpunkt further).


Nun wird die zweite Zeile zusammengefügt und in unserem Beispiel lagen nur zwei Zeilen vor - also geht es mit else goto final heraus aus dieser Schleife und ab in die nächste Schleife:

set /a y=1
:last
for /f "TOKENS=*" %%a in ('dir tablenew_%y%.log /b') do type "%%a" >> result.txt

Bis zum For Befehl ist alles klar. Wir setzen nun y=1 und schreiben die tablenew_1.log in eine Datei namens result.txt.
Bei jedem Durchlauf wird also eine nach der anderen Zeile in result.txt angefügt und die neue Tabelle aufgebaut: wie zuvor in der anderen Schleife...

set /a y=%y%+1
if exist tablenew_%y%.log (goto last) else goto nowend
:nowend

mit dem folgenden Ergebnis:

Name Vorname Geburtsdatum:   Adresse Plz:
Meyer Uli 10.10.1973: Berlin 10000:

Sieht zwar noch nicht sehr hübsch aus, aber das wird noch...

FOR /F "tokens=1,2 delims=:"  %%i  IN (result.txt) DO echo %%i%%j >>resulttwo.txt
del *.log

Am Ende werden die Doppelpunkte im resulttwo.txt ohne Doppelpunkte angezeigt, indem die Doppelpunkte wieder delims werden und wir %%i und %%j selektieren. Dabei fallen die Doppelpunkte weg - eigentlich ein Nebeneffekt, der hier gezielt eingesetzt wird.
Am Ende werden die ganzen Log-Dateien gelöscht, wodurch Sie wieder übersicht haben. Wenn Sie sich alle Ergebnisse mal ansehen wollen, dann lassen Sie den del *.log einfach weg - bei größeren Dateien ganz schön viel Holz...

Ach ja, keine Rose ohne Dornen:  Es bleiben drei Leerzeichen zwischen den beiden alten Tabellen als Altlast. Das ist für den Sternenhimmelstuermer kein Beinbruch, kommt aber darauf an.

Ginge auch anders - der Sternenhimmelstuermer sieht aber keinen Handlungsbedarf. Das Importieren in Excel geht dann im Ribbenmenü unter Externe Daten abrufen und dann das Textdokument importieren. Im Assistenten dann getrennt und im folgenden Fenster Leerzeichen auswählen - dann wird wieder alles ausgeglichen...

Ach ja, was passiert mit ü, ä und ß und Sonderzeichen- das typisch deutsche Problem: Beim Testen ging alles glatt! Die Variablen %%i und Co interessiert der Inhalt nicht...


Teil 4

Das Auslesen und Bearbeiten von Dateien würde der Sternenhimmelstuermer immer über in Zeilen zerlegte Reihen machen, deren Überschriften Zahlen sind. Wie das geht wurde gerade erklärt. Sie können sich das freilich viel einfacher machen. Nummerieren Sie die Zeilen zuvor mit Excel, gerne auch mit Überschriften und suchen Sie mit dem einfachen Befehl findstr in den durchnummerierten Dateien nach einem Stichwort.
Also jetzt eine fiktive Batch in der Art findstr "Name" "zahl_*.log", wenn Sie mit einfachen Zeilen arbeiten oder findstr "Name" "probe.txt">erg.log, wenn Sie konkret mit der Ursprungsdatei probe.txt arbeiten wollen.

Zur Erinnerung:

Inhalt probe.txt

Name Vorname Geburtsdatum
Meyer Manfred 20,02.1971
Miller Luise 03.03.1982

würde bei Eingabe  in cmd oder Batch von findstr "Name" "probe.txt">erg.log in windows 7 zu:

Name Vorname Geburtsdatum

führen.

Bei einer durchnummerierten Variante

1 Name Vorname Geburtsdatum

Hier verlassen wir bereits den Pfad der gemeinsamen Bearbeitung. Wie man das nun in Form bringt, haben Sie im Teil 2 und drei gelernt. Bei der Suche und Bearbeitung in einzelnen Zeilen mit Wildcrard Stern wird das ein wenig anders.
Beim Befehl findstr "Name" "*.txt">erg.log

erhalten Sie als Ergebnis: probe.txt:Name Vorname Geburtsdatum, bei relativer Lage der Batch und den Ergebnistexten.

Sie sehen, je nach herangehensweise unterscheiden sich die Ausgabearten und dementsprechend die Weiterbearbeitungsverfahrensweisen.  Dann könnten natürlich mehrere Ergebnisse in einer LogDatei stehen, wenn  das Suchergebnis mehrmals vorkommt.

Daher wäre es ratsam als Zwischenschritt mit einer x-Schleife das Ergebnis durchlaufen lassen - gibt es mehrere Ergebnisse, so werden die Zeilen wiederum getrennt - Sie kennen die Methode aus dem Kapitel 3.

Letzten Endes sind es aber nur tokens mit verschiedenen Delims die Sie mit ein wenig umstellen der For-Befehle aus Teil  2 und Teil 3 dieser Abhandlung  ersetzen, umstellen...oder was auch immer ...

Dazu brauchen Sie nur die Grundbefehle, die in dieser Abhandung vorgestellt wurden. Bei größeren Tabellen (mehrere hundert Zeilen) wird diese Art der Bearbeitung sehr schwierig - das war aber auch nie Anspruch dieser Abhandlung einer Nonprofitseite, die Amateueren ein wenig die Grundbefehle erklären wollte.

Aus dieser Abhandlung entstanden mehrere Folgeabhandlungen, was für den Laien nicht sofort ersichtlich ist. Die Jagd nach Doubletten von Dateien und Selektierung von Dateigrößen sind zwei Beispiele, wie Sie Tabellen mit Seperatoren erstellen und Verarbeiten. Alles mit den Grundlagen dieser Abhandlung!

Fazit

Die Tabellenbearbeitung mit wenigen Grundbefehlen ist möglich und mit den Grundlagen hier können Sie normale Aufgaben durchführen - Es gibt genug Foren im Netz: Der Sternenhimmelstuermer gibt auf Anschrift bezüglich individueller  Anfragen eine Nullauskunft.
Warum? Hier würden sonst nie neue Abhandlungen entstehen...und bei einer Lösung stellen sich dann diverse Nachfolgefragen.

Unumstritten hat die Sternenhimmelstuermer im Batchbereich mit die progessivsten veröffentlichten Batches eines Amateurs mit Erklärungen. Diese Abhandlungen könnten Sie interessieren:
Speicherfresserbatch Dokumente nach Größe suchen
Archivbatch Dokumente nach Jahren in Ordner sortieren
Windowshilfe Windowshilfe ausdrucken
switchbatch Zwischen Registrywerten switchen
Lernbatch Eine selbst lernende Batch

Excel dasselbe: Die Projekte der Sternenhimmelstuermerseite sind  auf hohem Niveau:
Ernährungstabelle
Numerologie
Kalender
Verexexcelung von Paragrafen
Anwesenheitslistenplan
Quartalsproblemlösung

genug Lesestoff und Probierstoff für Wochen und nur ein Bruchteil dieser Seite insgesamt...




Impressum
Datenschutz