saedelaere
Goto Top

Aus TXT Datei Variablen auslesen. TXT Datei ändert sich aber immer wieder.

Hi,

so bin ganz neu hier und will gleich was wissen.

Habe mich schon seit Jahren nicht mehr mit Batch Dateien beschäftigt und sitze jetzt an einem kleinen Programm.
Mein größtes Problem dabei sind immer noch FOR Schleifen.

Folgendes habe ich gemacht:

Erzeugen einer TXT Datei

FINDSTR /I /B "title" J:\boot\grub\menu.lst >>"%pfad%\Tests\menu_titles.txt"  

Dabei entsteht folgende TXT Datei:

title openSUSE 10.2 - 2.6.18.8-0.5
title Failsafe -- openSUSE 10.2 - 2.6.18.8-0.5
title Windows XP

Schön es wäre schon an dieser Stelle wenn das Wort "title" nicht mit auftauchen würde.
Aber egal mit Tokens kann ich dieses Wort ja rauskicken face-smile

Als nächstes würde ich gerne die erste Zeile ohne das Wort "title" als Variable übernehmen.
Dann die zweite Zeile und so weiter. Das Problem an der Sache ist, dass die TXT Datei nicht immer so aussehen muss. Es kann also sein, dass sie 5 Zeilen hat und in den Zeilen etwas anderes steht. Nur das Wort "title wird immer als erstes Wort in jeder Zeile auftauchen.

Mache ich folgendes

FOR /F "usebackq tokens=2-20" %%A IN ("%pfad%\Tests\menu_titles.txt") DO set var3=%%A %%B %%C %%D %%E  

gibt

echo %var3%

echo Windows XP

Logisch irgendwie, nur wie bekomme ich die ersten beiden Zeilen jeweils in eine Variable?
Hier noch die Datei menu.lst aus der ich meine TXT Datei erzeugt habe.

# Modified by YaST2. Last modification on Fr Aug  3 13:11:20 CEST 2007
default 0
timeout 60
gfxmenu (hd0,8)/boot/message

title openSUSE 10.2 - 2.6.18.8-0.5
    root (hd0,8)
    kernel /boot/vmlinuz-2.6.18.8-0.5-default root=/dev/hda9 vga=0x31a resume=/dev/hda8 splash=silent showopts
    initrd /boot/initrd-2.6.18.8-0.5-default

title Failsafe -- openSUSE 10.2 - 2.6.18.8-0.5
    root (hd0,8)
    kernel /boot/vmlinuz-2.6.18.8-0.5-default root=/dev/hda9 vga=normal showopts ide=nodma apm=off acpi=off noresume nosmp noapic maxcpus=0 edd=off
    initrd /boot/initrd-2.6.18.8-0.5-default

###Don't change this comment - YaST2 identifier: Original name: windows### 
title Windows XP
    rootnoverify (hd0,0)
    chainloader (hd0,0)+1

Bin für jeden Hinweis dankbar.

Viele Grüße
Saedelaere

Content-Key: 65594

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

Ausgedruckt am: 29.03.2024 um 06:03 Uhr

Mitglied: bastla
bastla 07.08.2007 um 01:37:21 Uhr
Goto Top
Hallo Saedelaere und willkommen im Forum1!

... nur wie bekomme ich die ersten beiden Zeilen jeweils in eine Variable?
Abgesehen davon, dass die Zwischendatei für den beschriebenen Zweck eigentlich nicht nötig wäre, ist die Frage eher anders zu stellen:

Was hast Du mit den einzelnen Variablen eigentlich vor? Benötigst Du alle einzelnen Zeilen in verschiedenen Variablen, oder soll ohnehin mit jeder Zeile das Gleiche gemacht werden, so dass ein Unterprogramm dafür ausreichen würde?

In letzterem Falle könntest Du etwa so vorgehen:
@echo off & setlocal
FOR /F "tokens=1*" %%A IN ('FINDSTR /I /B "title" J:\boot\grub\menu.lst') DO set "var3=%%B" & call :ProcessLine  
goto :eof
:ProcessLine
REM In %var3% steht jetzt die Zeile und kann verarbeitet werden (stellvertretend dafür ein "echo")  
echo %var3%
goto :eof

Grüße
bastla

[Edit] Da nur das erste Token entfernt werden soll, auf "1*" geändert. [/Edit]
Mitglied: Saedelaere
Saedelaere 07.08.2007 um 12:04:26 Uhr
Goto Top
Hi bastla,


das sieht schon mal gut aus. Leider brauche ich aber jede Zeile in einer eigenen Variablen.

Hinzu kommt noch, dass ich in dieser Datei gerne etwas einfügen würde. Es gibt den Wert "timeout" und "default".

In meiner Datei timeout = 60 default = 0. Kann ich den Wert 0 und 60 mit einer Batch Datei ersetzen?

Wenn nicht ist das nicht so schlimm. Wichtiger wäre mir mein erstes Problem.


Vielen Dank für die Hilfe!

Saedelaere

edit

Also ich komme auch mit deiner Programmzeile noch nicht weiter.
Durch echo %var3% wird nur die erste Zeile angezeigt.

FOR /F "tokens=1*" %%A IN ('FINDSTR /I /B "title" J:\boot\grub\menu.lst') DO set "var3=%%B" & call :ProcessLine  
goto :eof
:ProcessLine
REM In %var3% steht jetzt die Zeile und kann verarbeitet werden (stellvertretend dafür ein "echo")  
echo %var3%
ping -n 8 localhost >nul
goto :EOF

Die Ausgabe dieser Batch ist

openSUSE 10.2 - 2.6.18.8-0.5
Es folgt eine 8 sekündige pause
Failsafe -- openSUSE 10.2 - 2.6.18.8-0.5
Es folgt eine 8 sekündige pause
Windows XP

Ich will aber, dass alle drei Zeilen angezeigt werden. In meiner endgültigen Batch kommt zwar nicht dieser Ping Befehl, aber eine Abfrage mittels set /p.
Das funktioniert dann so aber nicht.
Mitglied: bastla
bastla 07.08.2007 um 17:23:20 Uhr
Goto Top
Hallo Saedelaere!

So ganz kann ich Dir noch nicht folgen, aber wenn Du alle Zeilen in eigenen Variablen haben willst, könntest Du so vorgehen:
@echo off & setlocal enabledelayedexpansion
set /a index=0
FOR /F "tokens=1*" %%A IN ('FINDSTR /I /B "title" Z:\boot\grub\menu.lst') DO call :ProcessLine "%%B"  
for /L %%i in (1,1,%index%) do echo !var%%i!
goto :eof
:ProcessLine
set /a index+=1
set "var%index%=%~1"  
goto :eof
Was Du dann anstelle der einfachen Ausgabe in der "for /L"-Schleife meines Beispiels mit den Variablen %var1% bis %varindex% machen willst, müsstest Du noch genauer erklären.
Zum Ersetzen ein Hinweis: Am elegantesten lässt sich derartiges mit "sed" (Download etwa über http://www.student.northpark.edu/pemente/sed/) erledigen, wenn die zu ersetzenden Teile allerdings anscheinend jeweils alleine in einer Zeile stehen, könntest Du etwa so vorgehen:
set "tList=%temp%\TempList.lst"  
if exist "%tList%" del "%tList%"  
for /f "delims=" %%i in (J:\boot\grub\menu.lst) do call :ProcessLine "%%i"  
move "%tList%" J:\boot\grub\menu.lst  
goto :eof
:ProcessLine
set "Line=%~1"  
if /i %1=="default 0" set "Line=default x"  
if /i %1=="timeout 60" set "Line=timeout y"  
echo %Line%>>"%tList%"  
goto :eof

Grüße
bastla
Mitglied: Biber
Biber 07.08.2007 um 18:33:56 Uhr
Goto Top
Moin Saedelaere,

Wenn es unbedingt ein Batch sein muss:
@FOR /F "tokens=1,2* delims= " %%A IN ('FINDSTR /I /B "title" menu.lst^|find /n "t"') do @Set "Var%%A=%%C"  
Danach steht alles was Du brauchst in den Variablen %Var1%, %Var2%, ...%VarN%.

Die kannst Du wiederum mit einer "FOR /F-Anweisung"rausflöhen:
Demo am CMD-Prompt:
>FOR /F "tokens=1,2* delims= " %A IN ('FINDSTR /I "title" menu.lst^|find /n "t"') do @Set "Var%A=%C"  
>for /f "tokens=1,* delims==" %i in ('set var') do @echo %i ist %j  
Var1 ist openSUSE 10.2 - 2.6.18.8-0.5
Var2 ist Failsafe -- openSUSE 10.2 - 2.6.18.8-0.5
Var3 ist Windows XP


Grüße
Biber
Mitglied: Saedelaere
Saedelaere 08.08.2007 um 20:40:22 Uhr
Goto Top
So erst mal tausend Dank für die professionelle Hilfe.

Habe mich mal ein wenig in Super Sed eingearbeitet. Ist ein sehr nützliches Tool.

Auch mit euren For Schleifen kann ich jetzt das machen was ich will.
Allerdings habe ich noch ein paar Probleme.

@Biber

Kannst du mir mal deine erste For Schleife erklären?

Ist es möglich festzustellen wieviele Variablen %VarN% jetzt vorliegen?

Mal angenommen ich habe eine Textdate in der X Zeilen stehen und in jeder Zeile ist ein beliebiges Zeichen. Kann ich diese X Zeilen dann auch als einzelne Variablen übernehmen?

Gerne werde ich hier meinen Code posten wenn ich fertig bin face-smile
Damit ihr auch sehen könnt, was ich aus euren Tips gemacht habe

Liebe Grüße
Saedelaere
Mitglied: Biber
Biber 08.08.2007 um 21:13:02 Uhr
Goto Top
Moin Saedelaere,

> Kannst du mir mal deine erste For Schleife erklären?
Nur die erste? Ich hätte Dir sonst auch auch den gesamten Batch erklärt... *gg

Die ganze Zeile...
@FOR /F "tokens=1,2* delims= " %%A IN ('FINDSTR /I /B "title" menu.lst^|find /n "t"') do @Set "Var%%A=%%C"  

FOR /F-Anweisungen immer gedanklich trennen und die Schnörkel weglassen:
 FOR /F ... %%A IN ('<i>irgendwasDasOutputSchreibt</i>') do <i>irgendwasOutputVerwertendes</i>  
und dann von innen ( "irgendwasDasOutputSchreibt" ) nach außen ("FOR /F ..IN xxxxxxx..DO whatever") lesen.

Also zuerst das "innen", das 'FINDSTR /I /B "title" menu.lst^|find /n "t"' lesen.
Das beginnt mit einem FINDSTR-Befehl, der nach "title" in der Datei menu.lst sucht.
Parameter: /I = Klein/Großschreibung egal ; Parameter /B: Am Zeilenanfang danach suchen

Dieser Teil ergibt z.B einen Output wie Du oben gepostet hast:
>FINDSTR /I /B "title" menu.lst  
title openSUSE 10.2 - 2.6.18.8-0.5
title Failsafe -- openSUSE 10.2 - 2.6.18.8-0.5
title Windows XP
>dieser Output wird sofort an den Find-Befehl übergeben, der jede Zeile mit einer Zeilennummer versieht.
^|find /n "t"' ..... (FIND sucht hier nach dem Buchstaben "t", der natürlich in jeder "title"-Zeile vorkommt.
Ergebnis:
[1]title openSUSE 10.2 - 2.6.18.8-0.5
[2]title Failsafe -- openSUSE 10.2 - 2.6.18.8-0.5
[3]title Windows XP
>das ist jetzt das Endergebnis von "innen", von "irgendwasDasOutputSchreibt".

So. Punkt. Absatz.
Jetzt "außen":
Diesen Output zerlege ich mit der FOR /F-Anweisung Zeile für Zeile
mit drei definierten Trennzeichen "[", "]" und " " (SPACE).
FOR /F "tokens=1,2* delims= " ....  
Ich behalte das 1. Token (die Zahl zwischen den Trennern "[" und "]" ) und alles nach dem 2. Token (Token 2 ist immer "title" wissen wir ja) .
@FOR /F "tokens=1,2* delims= " %%A IN ( meinOutputSieheOben ) do @Set "Var%%A=%%C"  
...und das erste Token -->%%A enthält die Ziffer und "alles nach dem zweiten Token" fange ich als %%C ein.

So, wenn Du das nach dem zweiten Lesen nachvollziehen kannst, dann versuche bitte, die von Dir noch gestellten Folgefragen selbst zu knacken.
Wenn es nicht klappt, sehen wir uns hier wieder.

Grüße
Biber