
65452
22.06.2010
Problem mit IF und FOR in der Batch
Ich stehe gerade auf dem Schlauch bei einer IF-Abfrage innerhalb einer FOR-Schleife!
Hallo,
ich habe eine Textdatei in der Form:
Diese Textdatei würde ich gerne in die Form
bringen.
Da dies in Zukunft häufiger vorkommen wird, dachte ich: "Mach dir eine Batch, das wird nicht allzu wild sein..."
Gesagt, getan:
Soweit so gut, nur sieht das Ergebnis leider so aus:
Kann mir bitte kurz jemand erklären, was ich falsch mache?
Ray
Hallo,
ich habe eine Textdatei in der Form:
zeile1
zeile2
zeile3
zeile4
zeile5
zeile6
Diese Textdatei würde ich gerne in die Form
zeile1;zeile2;zeile3;
zeile4;zeile5;zeile6;
bringen.
Da dies in Zukunft häufiger vorkommen wird, dachte ich: "Mach dir eine Batch, das wird nicht allzu wild sein..."
Gesagt, getan:
set zaehler=1
FOR /F %%i In (123.txt) Do (
Set /p =%%i;<nul>>result.txt
SET /A zaehler=%zaehler%+1
if %zaehler% == 4 (
ECHO.>>result.txt
) else (
ECHO Zaehler zu klein
)
)
Soweit so gut, nur sieht das Ergebnis leider so aus:
Zeile1;Zeile2;Zeile3;Zeile4;Zeile5;Zeile6;
Kann mir bitte kurz jemand erklären, was ich falsch mache?
Ray
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 145438
Url: https://administrator.de/forum/problem-mit-if-und-for-in-der-batch-145438.html
Ausgedruckt am: 17.05.2025 um 12:05 Uhr
11 Kommentare
Neuester Kommentar
Moin SL2MDS,
auch du kaufst deine Nicks offensichtlich nicht von der Stange...
Eine Skizze zum Weitertesten und Verfeinern könnte so aussehen:
und würde am CMD-Prompt folgenden Output liefern [führendes ">" ist mein Prompt; nicht mit eingeben]:
Erläuterung bzw. Strohhalme zum Weiterhangeln:
Für den CMD-Interpreter, der die Batch-Befehle abarbeitet, ist ein "FOR...In..DO( )" oder auch einer "IF ( ) ELSE ()" -Konstrukt immer EINE Zeile.
Auch wenn du sie optisch auseinanderziehst auf 2 DIN A4-Seiten.
In EINER zeile wird eine Variable %var% nur EINmal aufgelöst... wenn es losgeht mit der Ausführung.
Es sei denn, man/frau sagt an "Hey, mach mir verzögerte Variablenauflösung!" neudeutsch: "DelayedExpansion", Zeile 01".
Und nach der Ansage müssen die "verzögert aufzulösenden Variablen" als !var! statt %var% angesprochen werden.
Hilfe zu allen verwendeten Befehlen wie SetLocal, FOR, SET etc --> am CMD-prompt mit FOR/?, Set /? .....
[##Edit##]
Gerade gesehen, dass ich jeweil 4 "Zellen" zu einer neuen mache statt wie gefordert 3 Zeilen.
Nochmal:
... bei Änderung des Schnipsels auf:
[/##Edit##]
Grüße
Biber
auch du kaufst deine Nicks offensichtlich nicht von der Stange...
Eine Skizze zum Weitertesten und Verfeinern könnte so aussehen:
@echo off & setlocal EnableDelayedExpansion
::---zaehlerInFor.cmd-----Skizze, kein Produktiv-Batch ---
Set "outfile=result.txt"
:: Zum Testen reicht Ausgabe in Datei CON=Bildschirm
Set "outfile=Con"
set /a zaehler=0
set "oneLine="
FOR /F %%i In (123.txt) Do (
Set "Oneline=!oneline!;%%i"
SET /A zaehler=!zaehler!+1
if !zaehler! == 4 (
Set "zaehler=0"
ECHO.!oneline:~1!>>%outfile%
Set "oneLine="
) else (
ECHO [Debug] Zaehler ist !zaehler! OneLine ist "!Oneline!" ...weiter...
)
)
und würde am CMD-Prompt folgenden Output liefern [führendes ">" ist mein Prompt; nicht mit eingeben]:
>for /L %i in (1,1,9) do @echo zeile%i >>123.txt
>type 123.txt
zeile1
zeile2
zeile3
zeile4
zeile5
zeile6
zeile7
zeile8
zeile9
>zaehlerInFor.cmd
[Debug] Zaehler ist 1 OneLine ist ";zeile1" ...weiter...
[Debug] Zaehler ist 2 OneLine ist ";zeile1;zeile2" ...weiter...
[Debug] Zaehler ist 3 OneLine ist ";zeile1;zeile2;zeile3" ...weiter...
zeile1;zeile2;zeile3;zeile4
[Debug] Zaehler ist 1 OneLine ist ";zeile5" ...weiter...
[Debug] Zaehler ist 2 OneLine ist ";zeile5;zeile6" ...weiter...
[Debug] Zaehler ist 3 OneLine ist ";zeile5;zeile6;zeile7" ...weiter...
zeile5;zeile6;zeile7;zeile8
[Debug] Zaehler ist 1 OneLine ist ";zeile9" ...weiter...
Erläuterung bzw. Strohhalme zum Weiterhangeln:
Für den CMD-Interpreter, der die Batch-Befehle abarbeitet, ist ein "FOR...In..DO( )" oder auch einer "IF ( ) ELSE ()" -Konstrukt immer EINE Zeile.
Auch wenn du sie optisch auseinanderziehst auf 2 DIN A4-Seiten.
In EINER zeile wird eine Variable %var% nur EINmal aufgelöst... wenn es losgeht mit der Ausführung.
Es sei denn, man/frau sagt an "Hey, mach mir verzögerte Variablenauflösung!" neudeutsch: "DelayedExpansion", Zeile 01".
Und nach der Ansage müssen die "verzögert aufzulösenden Variablen" als !var! statt %var% angesprochen werden.
Hilfe zu allen verwendeten Befehlen wie SetLocal, FOR, SET etc --> am CMD-prompt mit FOR/?, Set /? .....
[##Edit##]
Gerade gesehen, dass ich jeweil 4 "Zellen" zu einer neuen mache statt wie gefordert 3 Zeilen.
Nochmal:
>zaehlerInFor.cmd
[Debug] Zaehler ist 1 OneLine ist ";zeile1" ...weiter...
[Debug] Zaehler ist 2 OneLine ist ";zeile1;zeile2" ...weiter...
[Output] zeile1;zeile2;zeile3
[Debug] Zaehler ist 1 OneLine ist ";zeile4" ...weiter...
[Debug] Zaehler ist 2 OneLine ist ";zeile4;zeile5" ...weiter...
[Output] zeile4;zeile5;zeile6
[Debug] Zaehler ist 1 OneLine ist ";zeile7" ...weiter...
[Debug] Zaehler ist 2 OneLine ist ";zeile7;zeile8" ...weiter...
[Output] zeile7;zeile8;zeile9
@echo off & setlocal EnableDelayedExpansion
Set "outfile=result.txt"
:: Zum Testen reicht Ausgabe in Datei CON=Bildschirm
Set "outfile=Con"
set /a zaehler=0
set "oneLine="
FOR /F %%i In (123.txt) Do (
Set "Oneline=!oneline!;%%i"
SET /A zaehler=!zaehler!+1
if !zaehler! == 3 (
Set "zaehler=0"
ECHO.[Output] !oneline:~1!>>%outfile%
Set "oneLine="
) else (
ECHO [Debug] Zaehler ist !zaehler! OneLine ist "!Oneline!" ...weiter...
))
Grüße
Biber

Nachdem ich heute (nein gerade gestern)
eine Batch Split-x.cmd gepostet habe, hier eine Join-x.cmd die als Alternative zu Bibers Version auch Ausrufezeichen im Text verarbeiten kann.
Gruß
LotPings
eine Batch Split-x.cmd gepostet habe, hier eine Join-x.cmd die als Alternative zu Bibers Version auch Ausrufezeichen im Text verarbeiten kann.
:: Join-X.cmd
@Echo off & Setlocal
Set InFile="123.txt"
Set Outfile=^>^>"123.new"
Type NUL %OutFile:~1%
Set X=3
Set "Line=" 2>Nul
For /F "tokens=1,* delims=" %%A in (
'find /N /V "#+#" ^< %InFile%'
) Do Call :ProcessLine %%A "%%B"
if defined Line %OutFile% Echo.%Line%
Goto :Eof
:ProcessLine
Set /A "Rest=%1 %% X "
Set Line=%~2;%Line%
If %Rest% EQU 0 (
%OutFile% Echo.%Line%
Set "Line="
)
Gruß
LotPings
Moin LotPings,
sieht ja vielversprechend aus...
Aber die Ausgabe ist noch leicht unterschiedlich, wenn ich deinen Schnipsel über die o.b. 123.txt laufen lasse.
Grüße
Biber
sieht ja vielversprechend aus...
Aber die Ausgabe ist noch leicht unterschiedlich, wenn ich deinen Schnipsel über die o.b. 123.txt laufen lasse.
>Join-X.cmd
(= 8:04:15 F:\schnipsel=)
>type 123.new
zeile3 ;zeile2 ;zeile1 ;
zeile6 ;zeile5 ;zeile4 ;
zeile9 ;zeile8 ;zeile7 ;
(= 8:05:11 F:\schnipsel=)
>zaehlerInFor.cmd|find /v "Debug"
[Output] zeile1;zeile2;zeile3
[Output] zeile4;zeile5;zeile6
[Output] zeile7;zeile8;zeile9
Grüße
Biber

Moin Biber,
ich hab ja schonmal gesagt "Es ist schön das wir aufeinander aufpassen"
Der Fehler mit der Reihenfolge war von mir verschuldet, das mit dem Leerzeichen dazwischen liegt aber am Inhalt deiner Datei 123.txt.
Diese leicht geänderte Version mit integriertem Trim und zusätzlichem Echo auf den Bildschirm:
Kommt auch mit dieser erschwerten 123.txt klar
Was deine Version leider nicht tut, sie mag neben Ausrufe- keine Leerzeichen im Text und unterschlägt in der Ausgabe die Zeile 10.
Gruß
LotPings
Edit: Bei meiner Bildschirmausgabe hatte ich den Überhang bei nicht durch 3 teilbaren Zeilen auch vergessen, ist korrigiert.
ich hab ja schonmal gesagt "Es ist schön das wir aufeinander aufpassen"
Der Fehler mit der Reihenfolge war von mir verschuldet, das mit dem Leerzeichen dazwischen liegt aber am Inhalt deiner Datei 123.txt.
Diese leicht geänderte Version mit integriertem Trim und zusätzlichem Echo auf den Bildschirm:
:: Join-X.cmd
@Echo off & Setlocal
Set InFile="123.txt"
Set Outfile=^>^>"123.new"
Type NUL %OutFile:~1%
Set X=3
Set "Line=" 2>Nul
For /F "tokens=1,* delims=" %%A in (
'find /N /V "#+#" ^< %InFile%'
) Do Set /A "Rest=%%A %% X"&Call :ProcessLine %%B
if defined Line Echo %Line% & %OutFile% Echo.%Line%
Goto :Eof
:ProcessLine
Set Line=%Line%%*;
If %Rest% EQU 0 (Echo.%Line%
%OutFile% Echo.%Line%
Set "Line="
)
Kommt auch mit dieser erschwerten 123.txt klar
zeile 1
zeile 2
zeile 3!
zeile 4
zeile 5
zeile 6!
zeile 7
zeile 8
zeile 9 !
zeile 10
Was deine Version leider nicht tut, sie mag neben Ausrufe- keine Leerzeichen im Text und unterschlägt in der Ausgabe die Zeile 10.
Gruß
LotPings
Edit: Bei meiner Bildschirmausgabe hatte ich den Überhang bei nicht durch 3 teilbaren Zeilen auch vergessen, ist korrigiert.
Moin LotPings,
du hast natürlich Recht mit dem überzähligen Blank in der Testdatei 123.txt.
Und auch damit, dass ich mit der Mimik über DelayedExpansion Ausrufungszeichen nicht richtig gut verarbeiten kann.
Die überzähligen (nicht durch 3 teilbaren) Zeilenreste allerdings hatte ich nicht vergessen, sondern wollte dem geschätzten TO auch noch etwas übrig lassen.
Ich würde (wahrscheinlich) auch diese Anforderung mit einem "Call: ProcessNext" statt alles in den FOR..In..DO-Klammern lösen.
Mein Ansatzpunkt hier im Thread war aber, die vorhandenen Codezeilen mindestens wiedererkennbar zu erhalten.
Also wäre eine Weniger-Buggy-Proof-of-Concept-Version diese hier:
Änderungen:
Grüße
Biber
du hast natürlich Recht mit dem überzähligen Blank in der Testdatei 123.txt.
Und auch damit, dass ich mit der Mimik über DelayedExpansion Ausrufungszeichen nicht richtig gut verarbeiten kann.
Die überzähligen (nicht durch 3 teilbaren) Zeilenreste allerdings hatte ich nicht vergessen, sondern wollte dem geschätzten TO auch noch etwas übrig lassen.
Ich würde (wahrscheinlich) auch diese Anforderung mit einem "Call: ProcessNext" statt alles in den FOR..In..DO-Klammern lösen.
Mein Ansatzpunkt hier im Thread war aber, die vorhandenen Codezeilen mindestens wiedererkennbar zu erhalten.
Also wäre eine Weniger-Buggy-Proof-of-Concept-Version diese hier:
::---zaehlerMitDelayedExpansion.cmd
@echo off & setlocal EnableDelayedExpansion
Set "infile=%~dp0123.txt" && REM Bein Testen ist Infile=123.txt und wird ggf angelegt
IF not exist "%infile%" (for /L %%i in (1,1,22) do (echo altezeile%%i)>>%infile%)
Set "outfile=result.txt"
:: Zum Testen reicht Ausgabe in Datei CON=Bildschirm
Set "outfile=Con"
set /a zaehler=0
set "oneLine="
FOR /F "delims=" %%i In (%infile%) Do (
Set "Oneline=!oneline!;%%i"
SET /A zaehler=!zaehler!+1
if !zaehler! == 3 (
Set "zaehler=0"
ECHO.[Output] !oneline:~1!>>%outfile%
Set "oneLine="
) else (
ECHO [Debug] Zaehler ist !zaehler! OneLine ist "!Oneline!" ...weiter...
))
IF defined oneLine ECHO.[OutputRest] !oneline:~1!>>%outfile%
Änderungen:
- Testfile 123.txt wird ggf. angelegt
- eine "alteZeile" in der 123.txt kann nun auch Leerzeichen/mehrere Token enthalten
- Ein vorhandener Rest der "altenZeilen", der insgesamt keine "ganze" neue Outputzeile ergibt wird angezeigt.
(=12:08:36 F:\schnipsel=)
>zaehlerMitDelayedExpansion.cmd
[Debug] Zaehler ist 1 OneLine ist ";altezeile1" ...weiter...
[Debug] Zaehler ist 2 OneLine ist ";altezeile1;altezeile2" ...weiter...
[Output] altezeile1;altezeile2;altezeile3
[Debug] Zaehler ist 1 OneLine ist ";altezeile4" ...weiter...
[Debug] Zaehler ist 2 OneLine ist ";altezeile4;altezeile5" ...weiter...
[Output] altezeile4;altezeile5;altezeile6
[Debug] Zaehler ist 1 OneLine ist ";altezeile7" ...weiter...
[Debug] Zaehler ist 2 OneLine ist ";altezeile7;altezeile8" ...weiter...
[Output] altezeile7;altezeile8;altezeile9
[Debug] Zaehler ist 1 OneLine ist ";altezeile10" ...weiter...
[Debug] Zaehler ist 2 OneLine ist ";altezeile10;altezeile11" ...weiter...
[Output] altezeile10;altezeile11;altezeile12
[Debug] Zaehler ist 1 OneLine ist ";altezeile13" ...weiter...
[Debug] Zaehler ist 2 OneLine ist ";altezeile13;altezeile14" ...weiter...
[Output] altezeile13;altezeile14;altezeile15
[Debug] Zaehler ist 1 OneLine ist ";altezeile16" ...weiter...
[Debug] Zaehler ist 2 OneLine ist ";altezeile16;altezeile17" ...weiter...
[Output] altezeile16;altezeile17;altezeile18
[Debug] Zaehler ist 1 OneLine ist ";altezeile19" ...weiter...
[Debug] Zaehler ist 2 OneLine ist ";altezeile19;altezeile20" ...weiter...
[Output] altezeile19;altezeile20;altezeile21
[Debug] Zaehler ist 1 OneLine ist ";altezeile22" ...weiter...
[OutputRest] altezeile22
Grüße
Biber

Na dann hat Ray ja einiges zum Studieren,
denn auch aus Fehlern anderer kann man lernen.
Gruß
LotPings
Uuups, ich sehe gerade Rays Vorgabe war auch ein Semikolon am Ende der Zeile....
denn auch aus Fehlern anderer kann man lernen.
Gruß
LotPings
Uuups, ich sehe gerade Rays Vorgabe war auch ein Semikolon am Ende der Zeile....
Moin Lordchen,

Ich schneide doch ohnehin ein überzähliges ";" vom Beginn der Variable %OneLine% ab...
Wenn ich das ohnehin schon mal in der Hand habe, kann ich es doch am Ende der Variable wieder ankleben, oder?
Viele nennen mich auch "Biber, den Recycler"
Grüße
Biber
Zitat von @77559:
Na dann hat Ray ja einiges zum Studieren,
denn auch aus Fehlern anderer kann man lernen.
Kann er nicht aus seinen eigenen lernen, so wie wir es auch jeden gatesverdammten Tag wieder tun müssen? Na dann hat Ray ja einiges zum Studieren,
denn auch aus Fehlern anderer kann man lernen.
Uuups, ich sehe gerade Rays Vorgabe war auch ein Semikolon am Ende der Zeile....
Tja, mit meiner Strategie hab ich es da jetzt leichter.Ich schneide doch ohnehin ein überzähliges ";" vom Beginn der Variable %OneLine% ab...
Wenn ich das ohnehin schon mal in der Hand habe, kann ich es doch am Ende der Variable wieder ankleben, oder?
Viele nennen mich auch "Biber, den Recycler"
Grüße
Biber

Zitat von @Biber:
Kann er nicht aus seinen eigenen lernen, so wie wir es auch jeden gatesverdammten Tag wieder tun müssen?
Stimmt, statt Kreuzworträtsel oder Sudokus zu lösen mache ich lieber Batche mit Fehlern und lerne daraus.Kann er nicht aus seinen eigenen lernen, so wie wir es auch jeden gatesverdammten Tag wieder tun müssen?
Wenn ich das ohnehin schon mal in der Hand habe, kann ich es doch am Ende der Variable wieder ankleben, oder?
Nunja, eigentlich müsste deine Zeile 12 das semikolon nur am Ende anhängen statt dazwischen,dann kann in Zeile 16+21 statt
!oneline:~1!
einfach nur !oneline!
stehen.Viele nennen mich auch "Biber, den Recycler"
Wäre ja auch blöd wenn wir das Rad jedesmal neu erfinden würden Gruß
LotPings
Moin SL2MDS,
Ich wünsche euch beiden ein schönes Wochenende und hoffentlich einen freudigen Sonntag Nachmittag
Wünsche dir auch ein schönes Wochenende
Biber

Zitat von @65452:
mmmhhh,
...
Ich habe dank eurer tollen Beispiele nun so einiges mehr verstanden, als ich mir hätte erhoffen können.
Somit konnte ich zusammen mit ein paar anderen Skripten und Tools nun endlich eine (fast) automatische Pflege unseres DHCP-Servers
realisieren.
Ich finde es toll, wie ihr mir hier weitergeholfen habt und ziehe respektvoll meinen Hut vor euren Batch-Kenntnissen!
Danke schön. Das geht einem ja runter wie in Bad im Golf von Mexiko.mmmhhh,
...
Ich habe dank eurer tollen Beispiele nun so einiges mehr verstanden, als ich mir hätte erhoffen können.
Somit konnte ich zusammen mit ein paar anderen Skripten und Tools nun endlich eine (fast) automatische Pflege unseres DHCP-Servers
realisieren.
Ich finde es toll, wie ihr mir hier weitergeholfen habt und ziehe respektvoll meinen Hut vor euren Batch-Kenntnissen!
Ich wünsche euch beiden ein schönes Wochenende und hoffentlich einen freudigen Sonntag Nachmittag
Biber
P.S.: Nicks von der Stange sind doch langweilig...
Stimmt, und diese Billgimitate aus Rudis Resterampe oder aus dem TeDi haben meist nur 6 kryptische Ziffern und Grossbuchstaben...