Dieser Beitrag ist schon älter. Bitte vergewissern Sie sich, dass die Rahmenbedingungen oder der enthaltene Lösungsvorschlag noch dem aktuellen Stand der Technik entspricht.

FOR F mit einer variabelen Anzahl Tokens

Mitglied: Friemler

Die FOR /F-Schleife bietet ja bekanntlich die Möglichkeit, Eingabedaten in sog. Tokens zu zerlegen. Dazu muss die Anzahl der Tokens aber schon beim erstellen des Batchscripts bekannt sein. Was aber, wenn das nicht der Fall ist? Oder man ein universell verwendbares Script schreiben möchte, das flexibel bzgl. der Anzahl der Tokens ist?

Ich möchte im folgenden ein Verfahren (zwei Unterprogramme für Batchscripts) vorstellen, mit der sich eine variable Anzahl Tokens (1 bis 31) für die FOR /F-Schleife realisieren lässt. Anschließend folgen noch zwei Anwendungsbeispiele.




back-to-topAllgemeines


back-to-topWas sind Tokens?
Die FOR /F-Schleife ist zur Verarbeitung einfach strukturierter Daten gedacht. Die einzelnen Datenfelder müssen durch Trennzeichen (Delimiter) voneinander separiert sein. Das kann z.B. der Backslash in Dateipfaden oder das Semikolon in CSV-Dateien von Excel sein. Die Datenfelder zwischen diesen Trennzeichen werden als Tokens bezeichnet. Die Standard-Trennzeichen von FOR /F sind das Leer- und das Tabulatorzeichen. Es können aber auch (mehrere) eigene Trennzeichen definiert werden.


back-to-topNutzen des Verfahrens
Man kann ein Script so entwickeln, dass es für gleichartige Eingabedaten mit einer unterschiedlichen Anzahl Tokens ohne Anpassung verwendbar ist.



back-to-topDie Syntax der FOR /F-Schleife

Für ausführliche Informationen verweise ich auf mein Tutorial zur FOR-Schleife.



back-to-topDas Verfahren

Die Idee zu dem Verfahren kam mir, als mir auffiel, dass normale Umgebungsvariablen, deren Inhalt aus Bezeichnern von Laufvariablen der FOR /F-Schleife besteht, innerhalb einer Schleife sozusagen doppelt ausgewertet werden. Vor Beginn der Schleife werden sie erweitert (der Code enthält nun die Bezeichner der Laufvariablen) und während der Abarbeitung der Schleife werden dann die Laufvariablen erweitert.

Also müsste man
  1. eine Probe der Eingabedaten untersuchen, um herauszufinden, wie viele Tokens die Eingabedaten enthalten und
  2. eine Umgebungsvariable mit so vielen Bezeichnern für Laufvariablen füllen wie Tokens vorhanden sind.

Aufgabe 1 wird vom Unterprogramm CountTokens erledigt, Aufgabe 2 vom Unterprogramm GenVars.

Um den praktischen Nutzen zu erhöhen, legt GenVars noch eine weitere Variable an, die den Bezeichner der letzten auftretenden Laufvariablen enthält, die bei der Abarbeitung der FOR /F-Schleife dem letzten Token entspricht.

Durch einen Parameter von GenVars kann außerdem gesteuert werden, ob die Bezeichner der Laufvariablen in Anführungszeichen eingeschlossen werden sollen. Das ist dann von Bedeutung, wenn einzelne Tokens auch Leerzeichen enthalten könnten und so wie im Anwendungsbeispiel 2 nach der Erfassung einzeln weiterverarbeitet werden sollen.


back-to-topEinschränkungen
Natürlich gelten auch hier wieder die Einschränkungen des Batchscript-Interpreters in Bezug auf die Verarbeitung von Zeichenketten, die bestimmte Sonderzeichen enthalten (%, ", ^, usw.). Man muss sich eben sicher sein, dass diese Sonderzeichen nicht auftreten können.

Die Eingabedaten können aufgrund von Beschränkungen der FOR-Schleife minimal 1 Token und maximal 31 Tokens enthalten.



back-to-topDie Unterprogramme


back-to-topCountTokens
In Zeile 17 wird die Zeichenkette von allen Zeichen befreit, die dem angegebenen Trennzeichen entsprechen. Wenn diese neue Zeichenkette und die ursprüngliche danach gleich sind, wird die Verarbeitung abgebrochen.

Ansonsten wird in Zeile 20 der Zähler für die Tokens erhöht und in Zeile 22 die übergebene Zeichenkette um das erste Trennzeichen und alle Zeichen davor verkürzt. Danach wird wieder an den Schleifenanfang gesprungen.


back-to-topGenVars
Der Bezeichner für die erste Laufvariable wird der Variablen Tokens in Zeile 25 bzw. Zeile 27 zugewiesen, abhängig vom Parameter %3. Die weiteren Bezeichner werden in Zeile 36 bzw. Zeile 38 hinzugefügt. Vor die Bezeichner wird immer nur ein Prozentzeichen gesetzt, das genügt in diesem Fall. Durch die SHIFT-Befehle in Zeile 31 bzw. Zeile 41 wird der nächste gewünschte Bezeichner in die Parametervariable %1 verschoben. Der Zähler CNT läuft nur mit, damit auch der Fall "Anzahl der Tokens ist 1" korrekt behandelt werden kann.



back-to-topAnwendungsbeispiel 1

Man hat folgende Verzeichnisstruktur:
Aufgabe ist, die Dateien, die sich in den Verzeichnissen X_Rechnungen_Y befinden, in passwortgeschützte ZIP-Archive zu packen, die den Namen des Verzeichnisses erhalten, aus dem die enthaltenen Dateien stammen, z.B. Maier_Rechnungen_2009.zip. Diese Verzeichnisstruktur kann auf mehreren Rechnern existieren, immer unter einem anderen Basispfad mit einer verschiedenen Anzahl übergeordneter Verzeichnisse. Das ist zwar kein Real-World-Beispiel und zeugt von einer schlechten Organisation, aber das ist hier nicht das Thema.

Normalerweise müsste das Batchfile zur Erstellung der ZIP-Archive auf jeden Rechner angepasst werden. Durch dynamisch erzeugte Laufvariablen/Tokens kann das Verzeichnis Kunden auf der 1. bis (31-FolderDepth). Ebene einer Verzeichnisstruktur liegen. Die Variable FolderDepth gibt die Anzahl der Verzeichnisse unterhalb von Kunden an. Die Variable SrcDir muss immer einen vollständigen Pfad inkl. Laufwerk enthalten.
Die Variable LastToken enthält den Bezeichner der letzten automatisch erzeugten Laufvariablen, die hier den Namen des Verzeichnisses mit den zu verarbeitenden Dateien repräsentiert. Nur wenn diese Variable einen Inhalt hat, wird gerade die richtige Verzeichnisebene betrachtet, deshalb Zeile 18.



back-to-topAnwendungsbeispiel 2

Der Inhalt der Zellen einer Excel-Tabelle, die als CSV-Datei vorliegt, soll für jede Zelle einzeln weiterverarbeitet werden, unabhängig davon, wie viele Spalten die Tabelle hat. Die Anzahl der Spalten darf aber höchstens 31 sein.
Damit der Inhalt der Zellen auch Leerzeichen enthalten kann, wird hier der Parameter QUOTE benutzt. Die Bezeichner der Laufvariablen werden dadurch in Anführungszeichen gesetzt.

Der Inhalt einer Tabellenzeile steht für jeden Durchlauf der FOR-Schleife im Hauptprogramm in der Variablen Line zu Verfügung. Die Zelleninhalte sind durch Leerzeichen separiert und in Anführungszeichen eingefasst und können somit von der FOR-Schleife in Zeile 24 ausgegeben werden.


Gruß
Friemler

Content-Key: 167111

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

Ausgedruckt am: 17.09.2021 um 13:09 Uhr

Mitglied: mathe172
mathe172 13.06.2011 um 21:29:10 Uhr
Goto Top
Hallo,

zuerst mal: Gutes tut, wie immer :-) face-smile

Nur noch kurz eine Frage:
1. Warum ist in Beispiel 2 die Zeile 14 in der Schleife?
2.
Würde sich diese Idee nicht irgendwie so verwirklichen lassen?

MfG,
Mathe172
Mitglied: Friemler
Friemler 14.06.2011 um 13:57:53 Uhr
Goto Top
Hallo mathe,

Zu Frage 1:
Die Variable Tokens enthält doch die Bezeichner einer variablen Anzahl von Laufvariablen der FOR-Schleife. In Zeile 14 werden diese durch die Werte der zugehörigen Tokens ersetzt.

Zu Frage 2:
Sicher, in Bezug auf Beispiel 2 ließe sich Dein Code auch verwenden. Was ich daran aber nicht so gut finde ist die Ersetzung von Leerzeichen durch ein selten benutztes Zeichen. Evtl. ist genau dieses Zeichen doch mal im zu zerlegenden Text enthalten, kann man vorher ja nie wissen. Du hast hier zwar den Smily aus dem DOS-Zeichensatz verwendet, aber dieses Zeichen (und alle mit einem Code kleiner 32) kann ich im von mir favorisierten Texteditor TextPad nicht eingeben, müsste zur Änderung dieses einen Zeichens den Code extra in MS-Edit laden und ändern.

Das ganze war auch mehr zur Vorstellung eines Konzepts gedacht, sozusagen Grundlagenforschung für FOR in Batchscript. Und wie das mit Grundlagenforschung so ist: Wie man es sinnvoll einsetzt muss jetzt wieder ein anderer erforschen. ;-) face-wink

Gruß
Friemler
Mitglied: mathe172
mathe172 14.06.2011 um 16:45:21 Uhr
Goto Top
Hallo,

Die Idee zu dem Verfahren kam mir, als mir auffiel, dass normale Umgebungsvariablen, deren Inhalt aus Bezeichnern von Laufvariablen der FOR /F-Schleife besteht, innerhalb einer Schleife sozusagen doppelt ausgewertet werden. Vor Beginn der Schleife werden sie erweitert (der Code > enthält nun die Bezeichner der Laufvariablen) und während der Abarbeitung der Schleife werden dann die Laufvariablen erweitert.
Uups, sollte besser lesen ;-) face-wink

Zu 2.: Du hast wie immer recht, es ist ein gefährlich(und aufwendig). (Das muss ja niemand wissen ;-) face-wink)

MfG,
Mathe172
Mitglied: jeb-the-batcher
jeb-the-batcher 20.06.2011 um 14:23:47 Uhr
Goto Top
Hallo Friemler,

zwei Gedanken kamen mir da so.
Wieso nimmst du nicht einfach immer die Maximalanzahl an tokens an? Wenn es weniger sind ist es ja auch nicht tragisch.

Warum teilst du die einzelnen Zeilen nicht durch Linefeeds, dann fällt doch auch die Begrenzung auf maximal 31 Tokens/Spalten weg.

Also z.B. um eine CSV-Datei zu lesen


Beispiel Ausgabe:

Normalerweise kann man mit FOR /F einen String nur in einzelne Token zerlegen, mit Linefeeds kann man aber pro delim eine eigene Zeile erzeugen und daher auch beliebig viele "Spalten" bearbeiten.
Die # hänge ich vor jede Spalte damit ich auch die leeren Spalten erwische.

jeb
Mitglied: Friemler
Friemler 20.06.2011 um 15:38:23 Uhr
Goto Top
Hallo jeb,

Zitat von @jeb-the-batcher:
Wieso nimmst du nicht einfach immer die Maximalanzahl an tokens an? Wenn es weniger sind ist es ja auch nicht tragisch.
Beim Beispiel 1 ist es wichtig, an das letzte vorhandene Token heranzukommen.

Zitat von @jeb-the-batcher:
Warum teilst du die einzelnen Zeilen nicht durch Linefeeds
Weil das Deine Spezialtricks sind. ;-) face-wink

bastla hat mir per PN schon geschrieben, dass für Beispiel 1 diese Sache auch nicht notwendig ist. Und Beispiel 2 lässt sich im konkreten Fall sicher noch auf ein paar mehr Wegen lösen als denen, die von Mathe und Dir beschrieben wurden. Wie gesagt, es sollte nur ein Konzept vorgestellt werden. Evtl. ist es ja wirklich nicht praxisrelevant, aber evtl. auch gut zu wissen, dass es geht.

Gruß
Friemler
Heiß diskutierte Beiträge
question
Drucker Gäste WLANmarkaurelVor 1 TagFrageLAN, WAN, Wireless27 Kommentare

Hallo zusammen und bitte um eure Hilfe! Ich hab in einer kleinen Schule ein LAN aufgebaut. Mit der Zeit kam natürlich auch der Bedarf an ...

question
Virtualisierungsprojekt für die FacharbeitVentimonusVor 1 TagFrageVirtualisierung16 Kommentare

Heyho, Ich habe mal ein paar fragen, bezüglich meines Abschlussprojektes, ob das alles überhaupt so Sinnig ist wie ich es mir denke. Kurz zur Erläuterung: ...

general
HomeServer noch mal anfassen?dertowaVor 1 TagAllgemeinServer-Hardware20 Kommentare

Hallo zusammen, erst im Juli dieses Jahres habe ich mein Homeserver-System angefasst und ein paar Upgrades vorgenommen. Der Threadripper 1920x wurde durch einen Ryzen 5 ...

question
Netzwerkperformance - Mikrotik - Wo ist mein Fehler?BirdyBVor 19 StundenFrageNetzwerke34 Kommentare

Moin zusammen, ich stehe gerade etwas auf dem Schlauch und weiß nicht so recht was mein Fehler ist. Gegeben ist mein heimisches Netzwerk: Also eigentlich ...

info
Hunderttausende MikroTik-Router sind seit 2018 angreifbarkilltecVor 1 TagInformationMikroTik RouterOS23 Kommentare

Mehrere MikroTik Router angreifbar. Hier der Link zu Heise: Hunderttausende MikroTik-Router sind seit 2018 angreifbar Gruß ...

question
Neue Firmennetzwerkstruktur und ein glühender KopfDerWachnerVor 1 TagFrageNetzwerke28 Kommentare

Moin zusammen, nun hab ich jahrelang hier nur mitgelesen, nun stehe ich allerdings selbst vor nem Problem was mir seit Tagen Kopfschmerzen bereitet. Also wir ...

question
An Konsole geht der Root Account über SSH Permission denieditnirvanaVor 1 TagFrageUbuntu22 Kommentare

Hallo, wenn ich bei Ubuntu 16.04 über SSH einlogge, kommt Permission denied. Bin ich aber direct an der Konsole im VMWARE geht der Root User. ...

general
Neue Herausforderungen auf unserer englischen SeiteFrankVor 19 StundenAllgemeinOff Topic12 Kommentare

Auf unserer englischen Seite gibt es neue Herausforderungen: Find who restarted DB server und Wanted: Network Node Manager 6.4 wer kann helfen? Generell findet ihr ...