Batch Zeile aus Txt-Datei auslesen & ändern

o0Julia0o

nicht mehr wegzudenken
hallo

ich möchte eine Zeile aus einer Textdatei auslesen & dann ändern(ohne Nachfragen oder Bestätigungen von Windows). Wie kann ich das machen?

Code:
find "serveralTextures:true" "C:\Dokument.txt">temp.txt

Inhalt der Dokument.txt
Code:
farbe:true
lachen:true
gesicht:1.0
serveralTextures:true
hund:false

Die Zeile: "serveralTextures:true" soll gefunden werden. Dann ist alles o.k.(goto Ende).
Wenn sie allerdings so aussieht: "serveralTextures:false", dann soll sie geändert werden auf: "serveralTextures:true".

oder kann man so etwas kompliziertes gar nicht mehr mti ner Batch-Datei hinbekommen?

lieben Dank :)

Julia
 
Zuletzt bearbeitet:
Möglich ist es, es ist nur die frage ob es sich auszahlt oder nicht besser gelöst wäre mit einem script in z.b. AutoHotkey.

However, die Lösung zu deinem Problem lautet:
Code:
@echo off

set target=serveralTextures
set value=true
set file=dokument.txt

setlocal ENABLEDELAYEDEXPANSION
for /f "tokens=1,2* delims=:" %%i in (%file%) do (
	set nval=%%i:%%j
	if "%%i"=="%target%" (
		set nval=%%i:%value%
	)
	echo !nval!>>%file%.bak
)
del %file%
ren %file%.bak %file%
 
das ist ja wunderbar :) ich blicke nur nicht durch ;), aber egal.. bis auf folgendes:

Code:
@echo off

set target=serveralTextures
set value=true
set file=data\folder1\dokument.txt

setlocal ENABLEDELAYEDEXPANSION
for /f "tokens=1,2* delims=:" %%i in (%file%) do (
	set nval=%%i:%%j
	if "%%i"=="%target%" (
		set nval=%%i:%value%
	)
	echo !nval!>>%file%.bak
)
del %file%
ren %file%.bak %file%
...dann erstellt der eine dokument.bak(der Wert wird aber korrigiert). Also wenn ich die Zeile
Code:
set file=data\folder1\dokument.txt
so ändere.
 
Das liegt daran, dass der ren-Befehl ganz zum schluss mit doppelten Pfaden nicht klarkommt.
Ich hab den ren-Befehl durch move ersetzt, sollte jetzt auch mit einem Pfad statt nur einem Dateinamen funktionieren.

Code:
:: Ausgabe unterbinden
@echo off

:: Variablen setzen (file ist das Dokument)
set target=serveralTextures
set value=true
set file=data\folder1\dokument.txt

:: Befehlserweiterungen aktivieren damit in der for-schleife
:: die Variable verarbeitet werden kann.
setlocal ENABLEDELAYEDEXPANSION

:: für jede zeile in der Datei %file% teile sie bei dem Zeichen : (Doppelpunkt)
:: und weise den Teilen die Variablen %%i und %%j zu.
for /f "tokens=1,2* delims=:" %%i in (%file%) do (
	:: setze die den neuen string zusammen
	set nval=%%i:%%j
	:: wenn aber der Key (der erste teil der Zeile) der Variable %target% 
	:: (dem gesuchten Key) entspricht dann...
	if "%%i"=="%target%" (
		:: ...setze die variable neu zusammen
		set nval=%%i:%value%
	)
	:: schreibe den neuen String in eine neue Datei mit der zuätzlichen endung .bak
	echo !nval!>>%file%.bak
)
:: lösche die originaldatei
del %file%
:: benenne die *.bak datei auf den originalnamen um.
move %file%.bak %file%
 
hey supi, das funktioniert :) Ich mußte allerdings den code deiner 1. Version nehmen & dann unten die move-Stelle nutzen. Denn dein neuer code funktioniert so nicht. Keine Ahnung wo der Fehler liegt. Und danke für die Kommentare.. verstehe nun schon mehr. Steht das "1,2*" für jede Zeile?

julia :)
 
o_O

Weired, is derselbe code.
Anyway. Freut mich dass es bei dir funtkioniert.

Steht das "1,2*" für jede Zeile?
Nein, das definiert die anzahl der Variablen und was in den Variablen stehen soll.
"1" setzt den teil vor dem Doppelpunkt in die variable %%i und
"2" setzt den teil nach dem Doppelpunkt in die Variable %%j.

Das Asterisk (*) ist dabei wichtig, da es ja sein kann dass der Teil hinter dem Doppelpunkt nochmal einen Doppelpunkt erhält, und dann würden Teile flöten gehen.

Sprich:
"tokens=1,2" bei dem String "gesicht:1.0:Weiterer wichtiger Parameter" würde ausgeben:
%%i => gesicht
%%j => 1.0

hingegen bei "tokens=1,2*" und demselben string kommt:
%%i => gesicht
%%j => 1.0:Weiterer wichtiger Parameter
 
Wunderprächtig, aber Batch ist sowas von tot, sobald es granular werden soll. Für solche Zwecke eignet sich am einfachsten zu erlernen AutoIt
PHP:
$file1 = FileOpen("test.txt", 0)
$file2 = FileOpen("out.txt" , 2)

While 1
    $line = FileReadLine($file1)
    If @error = -1 Then ExitLoop

    $result = StringInStr($line, "serveralTextures:false")

    If $result = 0 Then
      FileWriteLine ( $file2, $line )
    Else
      FileWriteLine ( $file2, "serveralTextures:true" )
    EndIf      
Wend

FileClose($file2)
FileClose($file1)

FileCopy ( "out.txt", "test.txt", 1 )
FileDelete  ("out.txt")
Übersetzt:
- Öffne Datei 1 und 2.

Schleife:
- Lese aus 1 bis Dateiende erreicht (Schleife verlassen)
- Suche String ...
- Und verfahre nach Anweisung.
- Schreibe das Ergebnis in 2.
Schleife wiederholen

- Schliesse beide Dateien.
- Kopiere 2 nach 1
- Lösche 2

Das ist nur die einfachste Variante, lässt sich beliebig erweitern, verfeinern, Fehler abfangen.

Dazu benötigt Benutzer AutoIt als Entwicklungsumgebung. Portal - AutoIt.de - Das deutsche AutoIt-Forum
Allerdings können die Scripte dann auch direkt ausgeführt werden, wahlweise auch als EXE-Datei kompiliert. Mit Parametereingabe und sonstigem Schnickschnack, welches mit Batch nur schwerlich oder gar nicht machbar wäre.
 
danke für den Hinweis.. und jetzt habe ich gerade mit Autohotkey angefangen ;) wobei AutoIt noch interessanter aussieht. Meist reicht mir aber ohnehin ne Batch-Datei, wo ich mich zumal schon ein wenig auskenne.
 
ot:
Wunderprächtig, aber Batch ist sowas von tot...
Ich kenn zumindest n dutzend Administratoren die dir da wiedersprechen würden weil sie noch immer teilweise Batch für Rollouts verwenden...


BTW: AutoIt is ja ganz nett, aber AutoHotkey mMn leichter zu lernen...
Code:
sfor := "serveralTextures"
nval := "false"
FileRead, content, % (dok := A_ScriptDir "\dokument.txt")
FileDelete, %dok%
rex := "i)" sfor ":(.+?)\R"
FileAppend, % RegExReplace(content, rex, sfor ":" nval "`r`n"), %dok%
 
Das von dir angesprochene Programm (AutoHotkey) kenne ich nur dem Namen nach, aber dein Beispiel ist beeindruckt ;)

Batch zur Administration mag ich nicht verneinen, nutze ich selbst für mein Netzwerk. Nur käme ich nicht mehr auf die Idee, hochkomplexe Vorgänge in 16 Bit in der DosBox auszuführen. Selbst meine ersten Wege über c++ in der Box (gcc, mingw) waren zwar schnell, aber immer noch langsam. Auch die vorgefertigten Tools aus der GNU-Reihe waren langsam. Für andere Projekte nutze ich eine weitere modulare (Bibliotheken) Scriptsprache, die aber direkt auf c++ 32bit setzt. Für VC direkt habe ich nicht genügend Zeit, leider. MfG
 
was man so liest, ist AutoHotKey tatsächlich einfacher, aber AutoIt dafür halt komplexer. Und die gängigen Browser können dann den Code verstehen & umsetzen?
Das wäre ja noch ein klitzekleiner Vorteil für Batches, die selbst ohen Browser laufen.
 
Was AutoHotkey angeht so ist mir keine Methode bekannt wie der Code direkt mit oder durch den Browser interagieren könnte.
AFAIK brauchen sowohl AutoHotkey als auch AutoIT einen Interpreter solange der Code nicht kompiliert wird, was zumindest bei AutoHotkey nichts anderes heisst als dass der Code mit dem Interpreter gepackt und komprimiert wird.
 
aso, also ähnlich wie bei C++, das Ergebnis ist dann eine ausführbare exe. Aber jeder der kein AutoIT/AutoHotKey selbst installiert hat, kann die exe dennoch ausführen?
 
so.. jetzt habe ich mich selbst mal an deinem code probiert... mit mehr und weniger Erfolg :)

Original-Code:
Code:
@echo off
set target=serveralTextures
set value=true
set file=data\folder1\dokument.txt

setlocal ENABLEDELAYEDEXPANSION
for /f "tokens=1,2* delims=:" %%i in (%file%) do (
	set nval=%%i:%%j
	if "%%i"=="%target%" (
		set nval=%%i:%value%
	)
	echo !nval!>>%file%.bak
)
del %file%
move %file%.bak %file%
setlocal DISABLEDELAYEDEXPANSION
exit
...funktioniert perfekt. Ich möchte ihn aber erweitern, weil ich einfach noch eine 2. Zeile ändern möchte. Hier meine 2 Versuche:

1. mehr Erfolg:
Code:
@echo off
set target=serveralTextures
set value=true
set file=data\folder1\dokument.txt

setlocal ENABLEDELAYEDEXPANSION
for /f "tokens=1,2* delims=:" %%i in (%file%) do (
	set nval=%%i:%%j
	if "%%i"=="%target%" (
		set nval=%%i:%value%
	)
	echo !nval!>>%file%.bak
)
del %file%
move %file%.bak %file%


set target=serveralTextures2
set value=
set file=data\folder1\dokument.txt

for /f "tokens=1,2* delims=:" %%i in (%file%) do (
	set nval=%%i:%%j
	if "%%i"=="%target%" (
		set nval=%%i:%value%
	)
	echo !nval!>>%file%.bak
)
del %file%
move %file%.bak %file%
setlocal DISABLEDELAYEDEXPANSION
exit
...das Funktioniert. Der Wert soll bei SeveralTextures2 nicht auf "true" sondern auf "" gesetzt werden.

Ich möchte das aber effizenter haben, mein Versuch mit weniger Erfolg:
weniger Erfolg:
Code:
@echo off
set target=serveralTextures
set target=serveralTextures2
set value=true
set value2=
set file=data\folder1\dokument.txt

setlocal ENABLEDELAYEDEXPANSION
for /f "tokens=1,2* delims=:" %%i in (%file%) do (
	set nval=%%i:%%j
	if "%%i"=="%target%" (
		set nval=%%i:%value%
	)
	if "%%i"=="%target2%" (
		set nval=%%i:%value2%
	)
	echo !nval!>>%file%.bak
)
del %file%
move %file%.bak %file%
setlocal DISABLEDELAYEDEXPANSION
exit

ich denke, man kann sehen was ich möchte. Oder ist meine 1. Lösung bereits die optimale?

lieben dank

Julia :)

P.S.
oh man.. klappt ja doch! juchu :).. aber jetzt bin ich so stolz auf mich, da lasse ich das auch noch stehen :)..wer weiss, vielleicht braucht das ja noch mal einer :)
 
Zuletzt bearbeitet:
Nur so als Ergänzung: wenn es um eine skriptbasierte Umsetzung geht, die auf jdem (aktuellen) System läuft ist PowerShell recht geeignet:

Code:
$file = 'dokument.txt'
$old = 'severalTextures:false'
$new = 'severalTextures:true'
(Get-Content $file) -replace $old,$new | Set-Content $file

Eine temporäre Datei ist hier unnötig, da die Quelle komplett eingelesen wird.

PowerShell ist seit Windows 7 standardmäßig vorhanden (für XP nachinstallierbar) und der designierte Nachfolger der alten Shell CMD.EXE.
 
Oben