klette84
Goto Top

Mit Batch in n Zeile schreiben

Hallo,

ich möchte gern in eine Bestimte Zeile in einer *.txt Datei schreiben. Könnt ihr mir weiter helfen?

Ich bin so weit gekommen das er mir die bestimmten Zeilen in den geschrieben werden sollen aus giebt.

FOR /F "delims=:" %%A IN ('findstr /N .* "1000.txt"') DO set Zeilen=%%A

echo es sind %Zeilen% Zeilen

set /a zehn=%Zeilen%/10
echo 10%% = %zehn%

set /a zwanzig=%zehn%*2
echo 20%% = %zwanzig%

set /a dreissig=%zehn%*3
echo 30%% = %dreissig%

set /a vierzig=%zehn%*4
echo 40%% = %vierzig%

set /a fuenfzig=%Zeilen%/2
echo 50%% = %fuenfzig%

set /a sechzig=%zehn%*6
echo 60%% = %sechzig%

set /a achzig=%zehn%*8
echo 80%% = %achzig%

set /a neunzig=%zehn%*9
echo 90%% = %neunzig%

echo 100%% = %Zeilen%


pause
goto :eof

Wie bekomme ich es hin das er mir die zB. 40% in die n-Zeile schreibt?

Content-Key: 194030

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

Printed on: April 25, 2024 at 22:04 o'clock

Member: bastla
bastla Nov 10, 2012 updated at 08:54:34 (UTC)
Goto Top
Hallo Klettte64!

Unabhängig davon, was Du eigentlich vorhast (denn davon wissen wir ja nix, wie auch nicht über den Inhalt der bereits vorhandenen Zeilen in der Textdatei) könntest Du mit dem folgenden Batch den Inhalt einer Variablen %Zeile% in die in der Variablen %ZeilenNr% festgelegte Zeile der bestehenden Textdatei "1000.txt" schreiben und deren übrige Zeilen unverändert (außer, diese würden mit ":" beginnen) übernehmen:
@echo off & setlocal
set "Ordner=D:\Dein Ordner"  
set "Datei=1000.txt"  
set /a ZeilenNr=15
set "ZeileNeu=Neue Zeile"  

move "%Ordner%\%Datei%" "%temp%\%Datei%"  
(for /f "tokens=1* delims=:" %%i in ('findstr /n "^" "%temp%\%Datei%"') do (  
    if %%i neq %ZeilenNr% (echo(%%j) else (echo %ZeileNeu%)
))>"%Ordner%\%Datei%"  
Grüße
bastla
Member: Klette84
Klette84 Nov 10, 2012 at 13:07:56 (UTC)
Goto Top
Danke für die schnelle Antwort leider ersetzt er mir die n-Zeile und fügt keine neue ein...

Das ganze wird für ein Schlichtprogramm an der CNC-Maschine benötigt. Da diese Programme per CAD/CAM erstellt werden und zum teil Stunden dauern bis sie abgearbeitet sind.

Da her die Idee per Batch die Datei einlesen, herausfinden wie viele Zeilen es sind und bei der n-Zeile von 10% 20% 30% usw. eine neue Zeile einfügen mit MSG("Programm bei x %"). So bekomme ich am Monitor eine Anzeige und kann ca sagen wann der Programmablauf fertig ist.

Ich wollte es erst mal einfach an einer *.txt Datei testen. Später werden es *.mpf Datein sein...
Member: bastla
bastla Nov 10, 2012 updated at 14:58:52 (UTC)
Goto Top
Hallo Klette84!

Naja, "in Zeile n schreiben" ist für mich etwas anderes als "in Zeile n eine Zeile einfügen" - das würde ich für Deine (jetzt klare) konkrete Situation eher so machen:
@echo off & setlocal
set "Ordner=D:\Dein Ordner"  
set "Datei=1000.txt"  

move "%Ordner%\%Datei%" "%temp%\%Datei%"  
for /f %%i in ('find /c /v "$$$$"^<"%temp%\%Datei%"') do set /a ZeilenGesamt=%%i  
set /a Zehntel=ZeilenGesamt/10
set /a Stufe=1
set /a Z=Zehntel
for /f "delims=" %%i in ('findstr /n "^" "%temp%\%Datei%"') do set "Zeile=%%i" & call :ProcessLine  
goto :eof

:ProcessLine
setlocal enabledelayedexpansion
>>"%Ordner%\%Datei%" echo(!Zeile:*:=!  
endlocal
set /a Z-=1
if %Z%==0 (
    if %Stufe% lss 10 >>"%Ordner%\%Datei%" echo echo Programm bei %Stufe%0 %%  
    set /a Z=Zehntel
    set /a Stufe+=1
)
goto :eof
Die Schreibweise der Zeilen 14 bis 16 ist nur eine Vorsichtsmaßnahme, um die Originalzeilen exakt gleich (trotz ev Sonderzeichen, ":" am Anfang) in die (neue) Datei schreiben zu können.

Wenn die Zerlegung anhand des ":" problemlos funktioniert, kann das noch vereinfacht werden auf zB (ungetestet)
@echo off & setlocal
set "Ordner=D:\Dein Ordner"  
set "Datei=1000.txt"  

move "%Ordner%\%Datei%" "%temp%\%Datei%"  
for /f %%i in ('find /c /v "$$$$"^<"%temp%\%Datei%"') do set /a ZeilenGesamt=%%i  
set /a Zehntel=ZeilenGesamt/10
set /a Stufe=1
for /f "tokens=1* delims=:" %%i in ('findstr /n "^" "%temp%\%Datei%"') do call :ProcessLine %%i "%%j"  
goto :eof

:ProcessLine
>>"%Ordner%\%Datei%" echo(%2  
set /a Mod=%1 %% Zehntel
if %Mod%==0 (
    if %Stufe% lss 10 >>"%Ordner%\%Datei%" echo echo %Stufe%0 %%  
    set /a Stufe+=1
)
goto :eof
Grüße
bastla
Member: Klette84
Klette84 Nov 10, 2012 at 16:14:53 (UTC)
Goto Top
Wahnsinn Danke! in Zeile 19 bzw 16 ist ein echo zu viel aber ansonsten alles bestens! Bin gespannt was bei der CNC-Maschine raus kommt.

ich würde mir das Skripten gerne noch etwas besser selber bei bringen. Kannst du mir ein gutes Buch empfehlen. Da mir die CMD mit /? nicht wirklich weiter hilft...

Bzw würde es den Rahmen sprengen wenn du mir jede Zeile einzeln erleuterst was welcher Befehl genau bewirt.
Member: bastla
bastla Nov 10, 2012 at 18:27:17 (UTC)
Goto Top
Hallo Klette84!
in Zeile 19 bzw 16 ist ein echo zu viel
Ich war davon ausgegangen, dass die Zeile in der Datei etwa
echo Programm bei 40 %
lauten soll - und dann braucht es beide "echo" ...
Zum Ablauf (der Version 1):
  • Die ersten Zeilen dürften selbsterklärend sein ...

  • In Zeile 5 wird die Datei in den %temp%-Ordner verschoben, damit sie am Original-Speicherort wieder erstellt werden kann.
  • Zeile 6 ermittelt die Gesamtzeilenanzahl (etwas schneller) mit einer alternativen Methode (hier kannst Du auch Deine ursprüngliche Variante verwenden) - da alle Zeilen gezählt werden sollen, wird ein Begriff, den es in der Datei nicht gibt, als "negatives" Suchkriterium (= finde alle Zeilen außer jenen, die diesen Suchbegriff enthalten) verwendet; als Ergebnis liefert "find" dann nur die Zeilenanzahl (womit das Durchlaufen aller Zeilen in der Schleife eingespart wird).
  • Zeile 7 ist klar (wobei anzumerken ist, dass das Ergebnis einer Division in Batch immer eine abgerundete ganze Zahl ist).
  • In Zeile 8 wird der Zähler für die Zehn-Prozent-Stufen vorbelegt und in Zeile 9 die Zeilenanzahl, die einem Zehntel der Datei entspricht (nach der also dann jeweils die Ausgabe erfolgen soll).
  • Die Schleife in Zeile 10 liest alle Zeilen der Datei aus (indem als Suchbegriff der "Zeilenanfang" - den hat tatsächlich jede Zeile - verwendet wird), packt die Zeile in eine Variable und ruft für jede Zeile das Unterprogramm ":ProcessLine" auf. Der "findstr"-Schalter "/n}" wird übrigens hier nicht für die Zeilennummer benötigt, sondern verhindert, dass Leerzeilen einfach übersprungen würden.
  • Das Hauptprogramm endet in Zeile 11 (ansonsten würde das Unterprogramm am Ende nochmals durchlaufen).

  • Im Unterprogramm wird zunächst der Teil der Zeile nach dem ersten ":" ausgegeben - dazu wird alles bis zum ersten ":" durch "Nichts" ersetzt (siehe dazu "set /?)". Die Einbettung in einen "delayedExpansion"-Bereich beugt dabei Problemen mit ev enthaltenen Sonderzeichen vor. Die Schreibweise "echo(" entspricht dem bekannteren "echo." (funktioniert aber lt jeb-the-batcher auch in bestimmten Situationen, in denen es mit "." oder "\" nicht ginge, weswegen ich dazu übergegangen bin, sie grundsätzlich zu verwenden) und sorgt dafür, dass eine Leerzeile auch "leer" (und nicht als "ECHO ist ausgeschaltet (OFF)." ausgegeben wird.
  • Zeile 17 reduziert den Wert des Zeilenzählers um 1, und in Zeile 18 wird festgestellt, ob es Zeit für die Ausgabe der Information ist. Da durch die Abrundung (s. o.) die 100 % meist bereits vor der letzten Zeile erreicht werden, wird die Prozentstufe nur bist 90 % ausgegeben.
  • Wenn die Ausgabe vorzunehmen war, wird der Zeilenzähler wieder auf ein Zehntel der Zeilen gesetzt und die Zehner-Prozentstufe um 1 erhöht.
  • Die Zeile 23 wäre, da sie die letzte Zeile im Batch ist, nicht nötig - es schadet aber nicht, das Unterprogramm damit abzuschließen (um ggf dahinter noch weitere Zeilen, etwa für ein zweites Unterprogramm, hinzufügen zu können).

Grüße
bastla
Member: Klette84
Klette84 Nov 14, 2012 at 06:57:07 (UTC)
Goto Top
Danke für dein ausführlichen Bericht. Ich hab aber schon wieder den nächsten hänger...

und zwar möchte ich das die *.bat im selbigen Ordner alle *.mpf Datein durch geht und den Fortschritt in die Datein schreibt.


echo.
echo.
set "Ordner=%~dp0"
for /f "delims=" %%i in ("%Ordner%*.mpf") do (set Datei=%%~nxi & call :Label)
goto :eof

:Label
move "%Ordner%%Datei%" "%temp%\%Datei%"
usw...

Das klapt mit der ersten Datei die er findet recht gut jedoch bricht er die for /f %%i ab! Was mache ich falsch?
Member: bastla
bastla Nov 14, 2012 at 07:13:44 (UTC)
Goto Top
Hallo Klatte84!

Du hast eine Mischung von "for" und "for /f" fabriziert - letzteres liest entweder den Inhalt einer Datei zeilenweise aus oder verarbeitet das Ergebnis eines Befehls (hier wäre "dir /b" gefragt) - daher eher:
for /f "delims=" %%i in ('dir /b "%Ordner%*.mpf"') do (set "Datei=%%i" & call :Label)
Grüße
bastla
Member: Klette84
Klette84 Nov 14, 2012 at 11:40:27 (UTC)
Goto Top
Super bastla!

leider giebt es immer noch ein kleinen Schöhnheitsfehler. Da die letzte Datei im Ordner 2 mal "gepatcht" wird. Also er schreibt 2 mal Programm bei X % in je 2 Zeilen.

Grüße Klette
Member: Klette84
Klette84 Nov 14, 2012 at 13:12:50 (UTC)
Goto Top
wenn man neben bei arbeitet, übersieht man was schnell... Natürlich fehlte das goto :eof !

Also HIER die fertige Batch:


@echo off & setlocal

echo.
set "Ordner=%~dp0"
for /f "delims=" %%i in ('dir /b "%Ordner%*.mpf"') do (set "Datei=%%i" & call :Label)
goto :eof

:Label
echo.
echo Bitte warten, Programm %Datei% wird aktualisiert!

move "%Ordner%%Datei%" "%temp%\%Datei%"
for /f %%i in ('find /c /v "$$$$"^<"%temp%\%Datei%"') do set /a ZeilenGesamt=%%i
set /a Zehntel=ZeilenGesamt/10
set /a Stufe=1
set /a Z=Zehntel
for /f "delims=" %%i in ('findstr /n "^" "%temp%\%Datei%"') do set "Zeile=%%i" & call :ProcessLine
goto :eof

:ProcessLine
setlocal enabledelayedexpansion
"%Ordner%%Datei%" echo(!Zeile:*:=!
endlocal
set /a Z-=1
if %Z%==0 (
if %Stufe% lss 10 >>"%Ordner%\%Datei%" echo MSG^("Programm bei %Stufe%0 %%"^)
set /a Z=Zehntel
set /a Stufe+=1
)
goto :eof

Vielen Dank für die schnelle Hilfe!!!

Grüße
Klette
Member: bastla
bastla Nov 14, 2012 at 14:15:05 (UTC)
Goto Top
Hallo Klette84!

Schön, dass es jetzt passt ... face-smile

Magst Du vielleicht noch abschließend die Möglichkeit der "Code"-Formatierung nutzen? Sieht nicht nur schöner aus, sondern ist auch besser zu lesen ...

Grüße
bastla
Member: Klette84
Klette84 Nov 16, 2012 at 08:59:04 (UTC)
Goto Top
na klar wuste nur nicht wie...

echo.
set "Ordner=%~dp0"  
for /f "delims=" %%i in ('dir /b "%Ordner%*.mpf"') do (set "Datei=%%i" & call :Label)  
goto :eof

:Label
echo.
echo Bitte warten, Programm %Datei% wird aktualisiert!

move "%Ordner%%Datei%" "%temp%\%Datei%"  
for /f %%i in ('find /c /v "$$$$"^<"%temp%\%Datei%"') do set /a ZeilenGesamt=%%i  
set /a Zehntel=ZeilenGesamt/10
set /a Stufe=1
set /a Z=Zehntel
for /f "delims=" %%i in ('findstr /n "^" "%temp%\%Datei%"') do set "Zeile=%%i" & call :ProcessLine  
goto :eof

:ProcessLine
setlocal enabledelayedexpansion
>>"%Ordner%%Datei%" echo(!Zeile:*:=!  
endlocal
set /a Z-=1
if %Z%==0 (
if %Stufe% lss 10 >>"%Ordner%\%Datei%" echo MSG^("Programm bei %Stufe%0 %%"^)  
set /a Z=Zehntel
set /a Stufe+=1
)
goto :eof
Member: Klette84
Klette84 Jun 20, 2013 at 07:16:50 (UTC)
Goto Top
Hallo,

Das Programm arbeitet einwandfrei! Leider hab ich ein neues Problem und komm mit dem Quellcode nicht zurcht!

Aktuell schreibt die Batch eine neue Datei und erweitert jeweils pro Eintrag um 1 Zeile in der was geschrieben wird!

---> MSG("Programm bei X0%")

Mein neues Problem besteht darin das ich um 2 Zeilen erweitern möchte und zwei unterschiedliche einträge machen möchte...

*
*
*
Q1999 = %STUFE%0
FN 16: F-PRINT TNC:\MELDUNGEN\UHR.txt / SCREEN:


Die neu geschriebene Datei wird bei einer Heidenhain Steuerung verwendet.
Q1999 = "Wert" ---> weist Q-Parameter neuen Wert zu
FN 16: F-Print ruft eine *.txt Datei auf die wiederum auf den Q-Parameter zurückgreift: "Programm bei %3.0LF Prozent", Q1999;

Ich hoffe ihr könnt mir weiterhelfen

Grüße

Klette
Member: bastla
bastla Jun 20, 2013 at 18:46:59 (UTC)
Goto Top
Hallo Klette84!

Wenn Du 2 Zeilen je Datei schreiben willst, sollte es doch genügen, die Zeile 24 auf etwas in der Art von
if %Stufe% lss 10 (
    >>"%Ordner%\%Datei%" echo MSG^("Programm bei %Stufe%0 %%"^)  
    >>"%Ordner%\%Datei%" echo MSG^("FN 16: F-PRINT TNC:\MELDUNGEN\UHR.txt / SCREEN:"^)  
)
zu erweitern ...

Grüße
bastla
Member: Klette84
Klette84 Jun 21, 2013 at 15:00:51 (UTC)
Goto Top
Nee du das geht so nicht ;)

jetzt schreibt er nach jeder Zeile die Gelesen wurde die 2 neuen Einträge hinzu!

Zu dem ist der Syntax auch falsch von den 2 Zeilen die er schreiben soll...

1. Zeile
Q1999 = %Stufe%0

2. Zeile
FN 16: F-PRINT TNC:\MELDUNGEN\UHR.txt / SCREEN:

also ohne MSG("xxxx")


haste ne Idee ???
Member: bastla
bastla Jun 21, 2013 updated at 19:43:18 (UTC)
Goto Top
Hallo Klette84!

Je Datei müsste das denn doch eher zwischen Zeile 14 und 15 (oder 15 und 16) passieren face-confused und dort dann etwa so:
>>"%Ordner%%Datei%" echo Q1999 = %%Stufe%%0  
>>"%Ordner%%Datei%" echo FN 16: F-PRINT TNC:\MELDUNGEN\UHR.txt / SCREEN:  
Grüße
bastla
Member: Klette84
Klette84 Jun 26, 2013 at 05:59:40 (UTC)
Goto Top
Ich hab das Problem gefunden, warum er mir nach jeder Zeile die neuen Einträge macht...

Richtig muß es so geschrieben werden:

setlocal
CLS
echo.
set "Ordner=%~dp0"  
for /f "delims=" %%i in ('dir /b "%Ordner%*.h"') do (set "Datei=%%i" & call :Label)  
echo.
echo Alle Datein bearbeitet. 
echo.
PAUSE
goto :TOP

:Label
echo.
echo    Bitte warten, Programm %Datei% wird aktualisiert!

move "%Ordner%%Datei%" "%temp%\%Datei%"  
for /f %%i in ('find /c /v "$$$$"^<"%temp%\%Datei%"') do set /a ZeilenGesamt=%%i  
set /a Zehntel=ZeilenGesamt/10
set /a Stufe=1
set /a Z=Zehntel
for /f "delims=" %%i in ('findstr /n "^" "%temp%\%Datei%"') do set "Zeile=%%i" & call :ProcessLine  
goto :eof

:ProcessLine
setlocal enabledelayedexpansion
>>"%Ordner%%Datei%" echo(!Zeile:*:=!  
endlocal
set /a Z-=1
if %Z%==0 ( 
	>>"%Ordner%%Datei%" echo Q1999 = %Stufe%0  
	>>"%Ordner%%Datei%" echo FN 16: F-PRINT TNC:\MELDUNGEN\UHR.txt / SCREEN:  
    	set /a Z=Zehntel
    	set /a Stufe+=1
)
goto :eof



Eine kleine Knobelfrage hätte ich noch.

Wie kann ich das Programm so umschreiben das er mir auf gar kein fall in den ersten 15 Zeilen ein Eintrag schreibt?

Hat den Hintergrund das am Anfang in der Datei diverse Sätze stehen die nicht getrennt werden dürfen. Danach kommen nur Punktangaben wo neue Einträge da zwischen passen.

Grüße

Klette
Member: bastla
bastla Jun 26, 2013 at 12:18:47 (UTC)
Goto Top
Hallo Klette84!

Ungetestet etwa so:
setlocal
set /a Ignore=15
CLS
echo.
set "Ordner=%~dp0"  
for /f "delims=" %%i in ('dir /b "%Ordner%*.h"') do (set "Datei=%%i" & call :Label)  
echo.
echo Alle Datein bearbeitet. 
echo.
PAUSE
goto :TOP

:Label
echo.
echo    Bitte warten, Programm %Datei% wird aktualisiert!

move "%Ordner%%Datei%" "%temp%\%Datei%"  
for /f %%i in ('find /c /v "$$$$"^<"%temp%\%Datei%"') do set /a ZeilenGesamt=%%i-%Ignore%  
set /a Zehntel=ZeilenGesamt/10
set /a Stufe=1
set /a Z=Zehntel
set /a ZNr=1
for /f "delims=" %%i in ('findstr /n "^" "%temp%\%Datei%"') do set "Zeile=%%i" & call :ProcessLine  
goto :eof

:ProcessLine
setlocal enabledelayedexpansion
>>"%Ordner%%Datei%" echo(!Zeile:*:=!  
endlocal
set /a ZNr+=1
if %ZNr% leq %Ignore% goto :eof
set /a Z-=1
if %Z%==0 ( 
	>>"%Ordner%%Datei%" echo Q1999 = %Stufe%0  
	>>"%Ordner%%Datei%" echo FN 16: F-PRINT TNC:\MELDUNGEN\UHR.txt / SCREEN:  
    	set /a Z=Zehntel
    	set /a Stufe+=1
)
goto :eof
Grüße
bastla