65452
Goto Top

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:

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

Content-Key: 145438

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

Printed on: April 18, 2024 at 04:04 o'clock

Member: Biber
Biber Jun 22, 2010 at 19:39:17 (UTC)
Goto Top
Moin SL2MDS,

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
... bei Änderung des Schnipsels auf:
@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...  
))
[/##Edit##]


Grüße
Biber
Mitglied: 77559
77559 Jun 22, 2010 at 22:07:27 (UTC)
Goto Top
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.
:: 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
Member: Biber
Biber Jun 23, 2010 at 06:06:31 (UTC)
Goto Top
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.

>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
Mitglied: 77559
77559 Jun 23, 2010 at 07:54:38 (UTC)
Goto Top
Moin Biber,

ich hab ja schonmal gesagt "Es ist schön das wir aufeinander aufpassen" face-wink

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.
Member: Biber
Biber Jun 23, 2010 at 10:09:06 (UTC)
Goto Top
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:
::---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.
Output:
(=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
Mitglied: 77559
77559 Jun 23, 2010 at 10:32:19 (UTC)
Goto Top
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....
Member: Biber
Biber Jun 23, 2010 at 14:26:53 (UTC)
Goto Top
Moin Lordchen,

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? face-wink

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
Mitglied: 77559
77559 Jun 23, 2010 at 14:35:07 (UTC)
Goto Top
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.
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 face-wink

Gruß
LotPings
Member: Biber
Biber Jun 25, 2010 at 15:30:27 (UTC)
Goto Top
Moin SL2MDS,

können wir denn noch auf dein Feedback hoffen, bevor die deutsche Nationalmannschaft wieder den Rückflug antritt?

Grüße
Biber
Mitglied: 65452
65452 Jun 25, 2010 at 15:43:16 (UTC)
Goto Top
mmmhhh,

eigentlich hatte ich bereits direkt nach euren tollen Ausführungen ein Feedback hiergelassen...

Muss mir wohl ein Fehler unterlaufen sein.

Also hier das Feedback:

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 face-wink

Ray

P.S.: Nicks von der Stange sind doch langweilig...
Member: Biber
Biber Jun 25, 2010 at 17:02:05 (UTC)
Goto Top
Moin SL2MDS,

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.

Ich wünsche euch beiden ein schönes Wochenende und hoffentlich einen freudigen Sonntag Nachmittag face-wink
Wünsche dir auch ein schönes Wochenende
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... face-wink