.sessl
Goto Top

Batch: FOR-IF-FOR Schleife und Var aus zwei Var zusammensetzen

Hallo zusammen,

ich hab "mal wieder" ein, eig. zwei Probleme, bei dem ich Eure Hilfe benötige, da mir das Netz nicht weiter helfen konnte, bzw. ich nicht genau wusste, wonach ich suchen sollte.
Zum ersten Problem:

Ich möchte aus der Datei %importlog% die letzte Zeile auslesen, sollte diese leer sein, hätte ich gern die vorletzte Zeile.
Ich weiß, dass in einer von beiden etwas drin steht, nur nicht genau in welcher, da gern mal eine Leerzeile angehängt wird.
Der Code ansich funktioniert als "Einzeiler", jedoch nicht in einer erweiterten IF Abfrage.

for /f "delims=" %%a in ('powershell.exe -c "Get-Content '%importlog%' | Select-Object -last 1"') do (  
	if not defined %%a (
		for /f "delims=" %%a in ('powershell.exe -c "Get-Content '!importlog!' | Select-Object -last 2"') do (  
			set "msg2=%%a"  
		)
	) else (
		set "msg2=%%a"  
	)
)


Beim zweiten Problem geht es um die Zusammensetzung von Variablen aus bereits bestehenden Variablen!
%jobs% beinhaltet meine Backupjobs und ich möchte gern wissen, wie viele gelaufen sind.
Also lass ich durch die Subroutine an die Variable "job" die Jobnummer anhängen "job1", "job2", etc.. Dann möchte ich per einfacher IF Abfrage wissen, ob die benötigte Anzahl gelaufen ist, falls nicht möchte ich die Anzahl der Jobs ausgeben die gelaufen sind.

Also lasse ich mir mittels der Schleife noch mal für die Anzahl der Läufe die Nr. ausgeben und möchte den Jobnamen, der ja schon in den Variablen "job1", "job2", etc. drin steht ausgeben.
Jedoch bekomme ich es nicht hin, eine Variable aus zwei zusammen zusetzen, habe schon !var%%a!, %var[%%a]% und auch wenn ich vorher die Variable "joba" setze, klapt es nicht: %job!joba!%.
Setze ich jedoch manuell die Zahl ein: %job1% oder. !job! bekomme ich die Ausgabe wie gewünscht (beides funktioniert).

Gibt es eine Möglichkeit das so umzusetzen, bzw. nach was hätte ich online suchen müssen um eine Lösung zu finden?

set /a x=0
for /f "tokens=1 skip=2 delims= " %%a in ('%jobs%') do call :sub1 %%a  

if %x% NEQ 5 (
	if %x% NEQ 3 (
		echo %x% Jobs sind gelaufen
		for /l %%a in (1, 1, %x%) do (
			REM set "joba=%%a"  
			echo Job %%a:	!job%%a! >> %log%
		)
		goto mail
	)
)


:sub1
set /a x+=1

for %%a in (%1) do (
	set "job%x%=%1"  
)


Vielen Dank!!!

Viele Grüße
Tobias

Content-ID: 297027

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

Ausgedruckt am: 22.11.2024 um 01:11 Uhr

114757
Lösung 114757 22.02.2016, aktualisiert am 23.02.2016 um 16:23:39 Uhr
Goto Top
Mit Powershell aus den letzte beiden Zeilen die ermitteln welche nicht leer ist, kein Problem
powershell -command "@((gc '%importlog%' -tail 2 | ?{($_ -replace '\s','') -ne ''}))[-1]"  
Gibt immer die letzte Zeile mit Inhalt zurück. Einfach auf mehrere Zeilen erweiterbar indem man die Zahl bei -tail 2 wie gewünscht abändert.

Gruß jodel32
Friemler
Lösung Friemler 22.02.2016, aktualisiert am 23.02.2016 um 16:23:45 Uhr
Goto Top
Hallo Tobias,

zur Lösung Deines zweiten Problems ersetze die Zeilen 4 bis 21 Deines zweiten Scripts durch folgende Zeilen:
if %x% neq 5 if %x% neq 3 (
  echo %x% Jobs sind gelaufen

  for /l %%a in (1,1,%x%) do (
    call echo Job %%a: %%job%%a%%
  )
  
  goto :mail
)

exit /b 0


:sub1
  set /a x+=1
  call set "job%%x%%=%~1"  
exit /b 0

Wie funktioniert's? Du musst den Batchscript-Interpreter dazu zwingen, die Codezeilen, in denen Du Variablennamen dynamisch per Script erzeugst (die Zeilen 5 und 16 in meinem Schnipsel), zweimal zu parsen. Dazu steht der CALL-Befehl vor dem SET. Die Prozentzeichen um den dynamischen Teil des Variablennamens (in Zeile 5 komplett, in Zeile 16 bei der Zuweisung nur der numerische Teil) müssen dann verdoppelt werden.

Gruß
Friemler
Endoro
Endoro 23.02.2016 aktualisiert um 12:42:59 Uhr
Goto Top
Hey,
die letzte nicht-leere Zeile einer Textdatei bekommst du so:
@echo off & setlocal
for /f "usebackqdelims=" %%a in ("%importlog%") do set "letzte=%%a"  
echo %letzte%

Und die for-Schleife in deinem zweiten Code sollte so gehen:
for /f "usebackqskip=2" %%a in ("%jobs%") do call :sub1 %%a   

Hast du keine Fehlermeldung bekommen, etwa "is not recognized as an internal or external command,"?

Gruß, Endoro
.Sessl
.Sessl 23.02.2016 um 16:23:31 Uhr
Goto Top
Hi jodel32,

vielen Dank für die schnelle Hilfe und Lösung des ersten Problems!


Viele Grüße
Tobias
.Sessl
.Sessl 23.02.2016 um 16:26:17 Uhr
Goto Top
Hi Friemler,

vielen Dank für die Lösung des zweiten Problems!!
Wieder etwas gelernt und eine Schleife weniger die durchlaufen werden muss.

Danke!


Viele Grüße
Tobias
.Sessl
.Sessl 23.02.2016 um 16:33:01 Uhr
Goto Top
Hi Endoro,

danke für deine Antwort!

Zum Problem mit der letzten Zeile, ich hatte auch schon "usebackqdelims" probiert, jedoch scheint mit diesem Befehl die Logdatei nicht vollständig durchgegangen zu werden, da er mir als "letzte" Zeile eine aus der Mitte ausspuckt. Dieses Logfile hat akt. ca. 600k Zeilen, können aber weitaus mehr werden, da ist mir das mit PS schon sicherer.

Zum zweiten Code, die FOR-Schleife funktioniert, ruft jedoch ein externes Programm auf und übergibt die Dateien an die Subroutine:
for /f "tokens=1 skip=2 delims= " %%a in ('omnidb -session %SESSIONID%') do call :sub1 %%a  

Ich hatte nur das Problem mit den dynamischen Variablennamen.

Trotzdem Danke!

Gruß
Tobias