blacksun
Goto Top

Per Batch Zeilenweise aus einer Datei lesen - bei jedem Aufruf wird die nächste Zeile verwendet

und wenn Ende erreicht, soll wieder bei der ersten zeile begonnen werden

Hallo,

ich bräuchte mal wieder eure Hilfe bei der Erstellung einer Batch.

Und zwar geht es um folgendes.
Ich habe eine Datei, die pro Zeile einen Wert enthält.

z.B.

Hans
Peter
Gerda
...
Uwe


Ich möchte nun den jeweiligen Wert (also eine Zeile) auslesen und in einer Variablen verwenden.
Das könnte man ja mit

FOR %%f IN (datei.txt) DO echo %%f

welches hier Auslesen einzlner Zeilen aus einem TXT File mittels Batch beschrieben ist, bewerkstelligen.

Allerdings möchte ich nicht die einzelnen Werte am Stück auslesen.
Ich möchte, dass beim ersten Aufruf der Batch der Wert "Hans" ausgelesen und in eine Variable geschrieben wird. Beim zweiten Aufruf möchte ich den Wert "Peter" auslesen, usw.

Hinzu soll noch die Möglichkeit kommen, dass wenn man bei dem letzten Wert ist (in diesem Beispiel "Uwe"), dann soll die Batch beim nächsten Aufruf wieder beim ersten Wert "Hans" beginnen.
Es wäre schön, wenn man nicht irgendwo definieren muss, wieviele Zeilen die Datei hat, sondern wenn bei Erreichen des Endes automatisch wieder bei der 1. Zeile begonnen wird.


Wiegesagt wer hat hier eine Idee für mich, wie ich das hinbekommen kann.


Viele Grüße
Martin

Content-Key: 75780

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

Printed on: April 23, 2024 at 20:04 o'clock

Mitglied: 58502
58502 Dec 11, 2007 at 22:55:51 (UTC)
Goto Top
Ohne externe Definition, sei es über die Registry, eine Datei oder das Systemenvironment geht das nicht, was du vorhast. Für das Setzen einer nichtflüchtigen Variablen benötigst du setx.exe aus den XP-Support-Tools.
Hellsehen kann auch das fortschrittlichste Betriebssystem (noch) nicht. face-smile
Member: blacksun
blacksun Dec 12, 2007 at 10:48:16 (UTC)
Goto Top
Hallo Siebenstein,

das ist klar, dass ich den verwendeten Wert in eine Variable schreiben muss.
Ich schreibe den Wert vor dem Beenden einfach in eine Datei und lese diesen beim nächsten Aufruf wieder von dort aus.

Das Problem ist aber, wie ich dann beim nächsten Aufruf nach dem Wert suche und dann die nächste Zeile als neuen Wert nehme.
Und die Sache mit EOF ist auch noch da. Sprich wenn die letzte Zeile erreicht wurde, soll wieder bei Zeile 1 gegonnen werden.

Viele Grüße
Martin
Mitglied: 58502
58502 Dec 12, 2007 at 10:54:16 (UTC)
Goto Top
Du musst die Anzahl der bereits ausgelesenen Zeilen ermitteln, den Wert in eine Variable oder Datei schreiben. Anhand dieser Variablen kannst du dann mit SKIP die gelesenen Zeilen übergehen. Wenn du alle geSKIPPED hast, ist die Variable doch leer, dann beginnst du halt von vorn.

Beenden/Abbrechen kannst du den Spaß mit goto :EOF
Member: blacksun
blacksun Dec 12, 2007 at 15:54:35 (UTC)
Goto Top
Hättest Du mir ein Beispiel, wie das aussehen könnte.

Also das mit einem Wert in eine Datei schreiben und diesen Wert wieder aus der Datei zu lesen, das bekomm ich noch hin.

Aber wie Suche ich beim nächsten Aufruf mit diesem SKIP?
Geht das mit einem FOR ....?

Und kann ich mit dem EOF aus dem FOR-Befehl wirklich feststellen, wann das Listenende erreicht wurde und dann wieder bei Zeile 1 anfangen???

Viele Grüße
Martin
Mitglied: 58502
58502 Dec 12, 2007 at 16:06:39 (UTC)
Goto Top
Wie skip funktioniert, steht in der Hilfe zu FOR, damit werden einfach n Zeilen übersprungen. Mit goto :eof beendest du nach skip und dem nachfolgen Lesen der nächsten Zeile (wenn eine da ist) den Ablauf. Wenn keine mehr da ist, dürfte die variable leer sein.

Ein fertiges Beispiel kannst du von mir nicht bekommen, nur Anregungen. face-wink
Nach meiner festen Überzeugung lernt man nur so den Umgang mit Batch-Scripten, und nur so bleibt auch was hängen.
Member: blacksun
blacksun Dec 12, 2007 at 16:18:43 (UTC)
Goto Top
also gut,

ich werd mich wenn es mir reicht heute abend mal intensiv mit dem FOR-Befehl beschäftigen.

das EOF gehört doch auch zum FOR-Befehl.

Und Du meinst wirklich, dass das, was ich wie beschrieben vor habe, so mit FOR möchlich ist? Brauch ich da nicht noch was anderes?

Nicht dass ich an der ganz falschen Stelle Suche.


Viele Grüße
Martin
Mitglied: 58502
58502 Dec 12, 2007 at 16:20:31 (UTC)
Goto Top
EOF ist das Dateiende der Batchdatei, das hat mit FOR wenig bis nichts zu tun. face-wink

Hier gibt es jede Menge Beispiele im Unterforum, etwas, aus dem du Teile entnehmen kannst, die auch erläutert sind, ist sicher dabei.
Member: blacksun
blacksun Dec 12, 2007 at 22:46:28 (UTC)
Goto Top
Hallo siebenstein,

also ich hab mir jetzt mal folgendes zusammengebastelt:

[code]
set skipVar=0
set rows=0
set /p skipVar=<skipCounter


FOR /F %%a IN (datei.txt) DO @set /a rows=rows + 1

IF /I %rows%-%skipVar% EQU 0 (set skipVar=0)


FOR /F "skip=%skipVar%" %%i IN (datei.txt) DO (@echo %i )

set /a skipVar=skipVar + 1
echo %skipVar% > skipCounter
[/code]

Nur das hilft mir jetzt nicht wirklich weiter, da jetzt zwar immer eine Zeile weniger, dafür aber jeweils immer der gesamte Rest an Zeilen ausgegeben wird.

Bsp.:
Inhalt datei.txt:
[code]
aaa
bbb
ccc
ddd
[/code]

Lasse ich obigen Code darüber laufen, erhalte ich beim ersten Aufruf folgendes:
aaa
bbb
ccc
ddd


Beim zweiten Durchlauf wird mittels SKIP die erste Zeile weggelassen:
bbb
ccc
ddd

usw.

ABER:
Ich brauche nicht den gesamten Rest, sondern nur die jeweils erste Zeile in einer Variablen.
Also beim ersten Durchlauf brauche ich z.B. aaa, beim zweiten Durchlauf soll die Variable den Wert bbb, und beim dritten Lauf ccc annehmen.

Hier komme ich jetzt nicht weiter.
Ich habe mir nun überlegt, ob ich nicht dynamisch Variablen anlegen lasse und lasse jeden noch aus der Datei ausgelesenen Wert in eine dynamische variable schreiben.
Ich ersetze dabei die oben FOR-Schleife oben durch diese Variante:

[code]
set counter=0

FOR /F "skip=%skipVar%" %%i IN (datei.txt) DO
(@set counter=counter+1
@set Wert%counter%=%%i
)
[/code]

Dann habe ich bei der jeweils ersten Zeile eines Durchlaufes in der Variablen "Wert1" der richtigen Wert stehen.
Sprich beim ersten durchlauf sollte das aaa sein, beim zweiten ist die erste zeile bbb, was dann auch in "Wert1" stehen sollte.

Allerdings funktioniert die FOR-Schleife so bei mir nicht.
Kannst Du mir sagen, wo der Fehler liegt? Ich kann doch hoffentlich zwei Befehle in "DO" ausführen lassen.
Oder vielleicht hast Du mir einen anderen Vorschlag.

Viele Grüße
Martin
Mitglied: 58502
58502 Dec 12, 2007 at 23:12:34 (UTC)
Goto Top
Als erst mal musst du die Rows so speichern, dass sie nach dem Beenden auch noch zur Verfügung stehen, dazu solltest du setx.com (Support-Tools) benutzen. Die normalen Variablen sind nämlich beim Schließen des Konsolenfensters weg.

if "%rows%=="" setx rows 0  
set rows1=%rows%
set irgendwas=

FOR /F "skip=%rows1%" %%i IN (datei.txt) DO  call :tuwas %%i  
goto :eof

:tuwas
rem den ausgelesenen Namen sichern
if "%1"=="" set rows=0 & setx rows 0 & goto :eof  

set irgendwas=%1
set /a rows1=+1
setx rows %rows1%

2 %% für Schleifenvariablen innerhalb der Batch, wenn du das direkt testest, darf die Schleifenvariable nur 1 % enthalten.

Nicht geprüft, ausprobieren musst du selbst.
Member: blacksun
blacksun Dec 13, 2007 at 00:28:35 (UTC)
Goto Top
Hallo Siebenstein,

das ist ein guter Tip mit dem

DO call :tuwas

In die Sprungmarke tuwas kann ich dann mehrere Befehle schreiben.

Und dass man auch Sprungmarken Parameter übergeben kann und man dann dort auf diese mit %1 zugreifen kann, war mir neu.

Für's erste hab ich nur noch eine Frage, die sich vielleicht böde anhört:

Mit dem DO call :tuwas

springst Du ja zu der Sprungmarke tuwas. Gibt es eigentlich eine Chance, dass man der Sprungmarke mitteilt, wann das Ende der Sprungmarke erreicht ist.

Selbst wenn ich darunter noch eine Sprungmarke :tuwasanderes habe, dann rauscht die FOR-Schleife bei Ihren durchgängen auch dort hindurch.
Weil eigentlich soll ja bei

set irgendwas=%1
set /a rows1=+1
setx rows %rows1%

Schluss sein, und alles was darunter kommt soll nicht pro Schleifendurchgang abgearbeitet werden.

Viele Grüße
Martin
Mitglied: 58502
58502 Dec 13, 2007 at 01:27:43 (UTC)
Goto Top
Ich will erst mal ein paar kleine Fehler beseitigen, das fertige Script bekommst du nicht, nur noch Tipps. So, wie der Code da steht, funktioniert er nicht face-wink

Beenden kannst du, wenn du am Ende des Calls, also als letzte Zeile exit eingibts.

Bei den Zeilen mit setx muss hinten noch ein -m ran, rows mit 0 geht nicht, dafür muss "" eingesetzt werden und wenn rows ="" ist, funktioniert die FOR-Schleife mit dem skip-Befehl nicht. Dann gutes Gelingen und fröhliche Bastelns. Kleiner Tipp noch: Du musst 2 bzw. 3 weitere Sprungmarken verwenden. face-wink

@echo off & setlocal
if not "%rows%=="" set rows1=%rows%  
set irgendwas=

FOR /F "skip=%rows1%" %%i IN (datei.txt) DO  call :tuwas %%i  
goto :eof

:tuwas
rem den ausgelesenen Namen sichern
if "%1"=="" set rows= & setx rows "" -m & goto :eof  

set irgendwas=%1
set /a rows1=+1
setx rows %rows1% -m
echo %irgendwas%
echo %rows1%
pause
exit
Member: blacksun
blacksun Dec 13, 2007 at 19:25:22 (UTC)
Goto Top
Hallo siebenstein,

so langsam wird das ja auch bei mir.

Mit dem Ende hab ich mich wohl falsch ausgedrückt. Ich meine damit nicht das Beenden der Batch (über exit), sondern das Ende der Sprungmarke.

Nehmen wir mal den Beispielcode:

[code]
FOR /F %%i IN (datei.txt) DO call :tuwas %%i


:tuwas
set irgendwas=%1
set /a rows1=+1
setx rows %rows1% -m
echo %irgendwas%
echo %rows1%


:tuwasanderes
echo "123"

[/code]


Wenn ich das so aufrufe, dann führt die For-Schleife für jeden Durchlauf ja die Sprungmarke :tuwas aus, führt aber auch alles darunter, also die Sprungmarke :tuwasanderes aus.
Sprich pro Schleifendurchlauf wird auch
echo "123" ausgeführt.

In :tuwasanderes steht aber Code, der erst nach der dem Durchlauf der Schleife ausgeführt werden soll. Schreibe ich aber nach echo %rows1% ein exit , dann wird nicht die Schleife beendet, sondern die ganze batch.

Ich bin also auf der Such nach einer Möglichkeit, dass nach echo %rows1% ein Schleifendurchlauf am Ende ist und der nächste Lauf der For-Schleife beginnen soll.

Viele Grüße
Martin
Mitglied: 58502
58502 Dec 13, 2007 at 19:42:09 (UTC)
Goto Top
Ein call eine Unterroutine ist das Gleiche, als wenn man eine externe Batch aufruft. Du musst die Unterroutine mit goto :eof beenden; die externe Bätch würde sich selbst beenden, wenn der Ablauf beendet ist. D. h. nach :tuwas und vor :tuwasanderes gehört ein goto :eof.

Ich will mal nicht so sein, sonst quälst du dich noch in Wochen. face-smile

Hier der funktionierende Code:
@echo off & setlocal
set rows1=
set irgendwas=

if not "%rows%"=="" goto :nichtleer  

:start
set parm="delims="  
set rows1=0

goto :weiter
FOR /F %parm% %%i IN (datei.txt) DO  call :tuwas %%i
goto :eof

:nichtleer
set rows1=%rows%
set parm="skip=%rows%"  

:weiter
FOR /F %parm% %%i IN (datei.txt) DO  call :tuwas %%i
goto :start

:tuwas
rem den ausgelesenen Namen sichern
if "%1"=="" set rows= & setx rows ""-m & goto :eof  

set irgendwas=%1
set /a rows1=rows1+1
setx rows %rows1% -m
echo %irgendwas%
rem echo %rows1%
pause
exit


Die Batch-Datei muss immer separat aufgerufen werden, nicht aus einem geöffneten Konsolenfenster, sonst funktioniert sie nicht. Wenn du das nicht willst, musst du die Variable ROWS in eine Datei oder in die Registry schreiben und damit verarbeiten.
Member: blacksun
blacksun Dec 13, 2007 at 20:30:31 (UTC)
Goto Top
genau das wäre die alternative gewesen, das mit der seperaten Batch-Datei. Allerdings mag ich da überhaupt nicht, wenn jede funktion in einer seperaten Datei steht, die dann wieder mit call aufgerufen wird. Außerdem stehen in einer mit call aufgerufenen 2. Batch die Variablen nicht zur Verfügung.
Von daher ist die Idee von Dir mit der Sprungmarke eine feine Sache.

jetzt versteh ich auch das mit :eof

for /f %%i (datei.txt) do call :tuwas %%i
startet die for-Schleife und ruft die Sprungmarke auf, so als würde man eine zweite Batch aufrufen. Und das Beenden der zweiten untergeordneten Batch passiert bei der Sprungmarke über goto :eof

Und was dann nach dem Ende de For-Schleife passieren soll, dafür schreibe ich dann goto :tuwasanderes

[code]
for /f %%i (datei.txt) do call :tuwas %%i
goto :tuwasanderes

:tuwas
befehle pro Schleifendurchgang
goto :eof

:tuwasanderes
befehle, die nach dem vollständigen Ende der Schleife ausgeführt werden sollen.
[/code]


Ich bastel bei meiner Idee mal noch ein wenig weiter und vergleiche dann mal, ob ich auf diesselbe Batch komme wie du.
Jetzt hast Du mich ganz angestachelt. Jetzt will ich das Problem mal ausfechten face-smile

Viele Grüße
Martin
Member: blacksun
blacksun Dec 13, 2007 at 20:51:37 (UTC)
Goto Top
Hallo siebenstein,

bin nun auch mit meiner Idee fertig:

[code]
set skipVar=0
set /p skipVar=<skipCounter
set rows=0
set Vornamen=nix
set counter=0

FOR /F %%a IN (datei.txt) DO @set /a rows=rows + 1

IF /I %rows%==%skipVar% (set skipVar=0)


IF %skipVar%==0 (
FOR /F %%i IN (datei.txt) DO call :tuwas %%i
) ELSE (
FOR /F "skip=%skipVar%" %%i IN (datei.txt) DO call :tuwas %%i
)
goto :machweiter


:tuwas
set Vornamen=%1
set /a counter=counter+1
set Wert%counter%=%Vornamen%
goto :eof


:machweiter
set /a skipVar=skipVar + 1
echo %skipVar% > skipCounter

REM ###### Hier wird das eingetragen, was mit der pro Aufruf #####
REM ###### ausgelesenen Zeile gemacht werden soll ################

echo %Wert1% >> Ergebnis.txt

[/code]

Was meinst Du, was könnte man hier verbessern?

Viele Grüße
Martin
Mitglied: 58502
58502 Dec 13, 2007 at 20:57:00 (UTC)
Goto Top
Ganz gegen meine Einstellung habe ich dir doch eine fertige Lösung präsentiert, dein Problemchen wäre damit gelöst.
Ohne dir zu nahe treten zu wollen, aber ich bin kein Ersatz für einen Programmierkurs. face-wink Lass mich da bitte raus. Du wirst das schon schaffen: Üben, üben, üben.
Member: blacksun
blacksun Dec 13, 2007 at 21:21:21 (UTC)
Goto Top
Hallo siebenstein,

so hab ich das auch nicht gemeint.
Nach langem Durchkämpfen hab ich nun doch ein mit Deiner Hilfe ein Batch-Skriptchen hinbekommen, das mein Problem löst.
Von daher hat Du nicht gegen Deine Einstellung verstoßen. face-wink

Auf jeden Fall erstmal ganz herzliches Dankeschön für Deine Hilfe.

Viele Grüße
Martin