Top-Themen

AppleEntwicklungHardwareInternetLinuxMicrosoftMultimediaNetzwerkeOff TopicSicherheitSonstige SystemeVirtualisierungWeiterbildungZusammenarbeit

Aktuelle Themen

Administrator.de FeedbackApache ServerAppleAssemblerAudioAusbildungAuslandBackupBasicBatch & ShellBenchmarksBibliotheken & ToolkitsBlogsCloud-DiensteClusterCMSCPU, RAM, MainboardsCSSC und C++DatenbankenDatenschutzDebianDigitiales FernsehenDNSDrucker und ScannerDSL, VDSLE-BooksE-BusinessE-MailEntwicklungErkennung und -AbwehrExchange ServerFestplatten, SSD, RaidFirewallFlatratesGoogle AndroidGrafikGrafikkarten & MonitoreGroupwareHardwareHosting & HousingHTMLHumor (lol)Hyper-VIconsIDE & EditorenInformationsdiensteInstallationInstant MessagingInternetInternet DomäneniOSISDN & AnaloganschlüsseiTunesJavaJavaScriptKiXtartKVMLAN, WAN, WirelessLinuxLinux DesktopLinux NetzwerkLinux ToolsLinux UserverwaltungLizenzierungMac OS XMicrosoftMicrosoft OfficeMikroTik RouterOSMonitoringMultimediaMultimedia & ZubehörNetzwerkeNetzwerkgrundlagenNetzwerkmanagementNetzwerkprotokolleNotebook & ZubehörNovell NetwareOff TopicOpenOffice, LibreOfficeOutlook & MailPapierkorbPascal und DelphiPeripheriegerätePerlPHPPythonRechtliche FragenRedHat, CentOS, FedoraRouter & RoutingSambaSAN, NAS, DASSchriftartenSchulung & TrainingSEOServerServer-HardwareSicherheitSicherheits-ToolsSicherheitsgrundlagenSolarisSonstige SystemeSoziale NetzwerkeSpeicherkartenStudentenjobs & PraktikumSuche ProjektpartnerSuseSwitche und HubsTipps & TricksTK-Netze & GeräteUbuntuUMTS, EDGE & GPRSUtilitiesVB for ApplicationsVerschlüsselung & ZertifikateVideo & StreamingViren und TrojanerVirtualisierungVisual StudioVmwareVoice over IPWebbrowserWebentwicklungWeiterbildungWindows 7Windows 8Windows 10Windows InstallationWindows MobileWindows NetzwerkWindows ServerWindows SystemdateienWindows ToolsWindows UpdateWindows UserverwaltungWindows VistaWindows XPXenserverXMLZusammenarbeit
GELÖST

Batch - mit Variablen rechnen oder inkrementieren?

Frage Entwicklung Batch & Shell

Mitglied: Jansen

Jansen (Level 1) - Jetzt verbinden

06.11.2005, aktualisiert 02.03.2016, 28535 Aufrufe, 7 Kommentare

Hallo!

Aus einer Textdatei nach folgendem Muster
01.
Wert: 10 
02.
blabla bleh strunz 
03.
Wert: 13 
04.
blubber blub göbel dum 
05.
Wert: 26
möchte ich die Summe der Zahlenwerte ermitteln. Mein Versuch sieht so aus

01.
@echo off 
02.
@set /a sum=0 
03.
@for /F "tokens=1,2" %%a in (c:\tmp.log) do ( 
04.
....@if "%%a"=="Wert:" ( 
05.
........@if NOT "%%b"=="0" ( 
06.
............@echo ZwWert=%%b 
07.
............@set /a sum=%sum%+%%b 
08.
............@echo ZwSum=%sum% 
09.
........) 
10.
....) 
11.
12.
@echo EndSum=%sum%
Links die erhoffte Ausgabe, recht die tatsächliche.
01.
ZwWert=10............ZwWert=10 
02.
ZwSum=10.............ZwSum=0 
03.
ZwWert=13............ZwWert=13 
04.
ZwSum=23.............ZwSum=0 
05.
ZwWert=26............ZwWert=26 
06.
ZwSum=49.............ZwSum=0 
07.
EndSum=49............EndSum=26
Wer kann mir sagen, wo es hier hakt und hat vor allem eine, gern auch alternative, Lösung?
Danke für alle Tips!

PS.
Zielsystem ist Win2K/XP, die betreffende Datei ist das Log von ntbackup, das auf "Ausgelassen:" und "Unterschiedlich:" geprüft werden soll. Perl, VBS etc. kommen aus "administrativen Gründen" leider nicht in Betracht.

PPS.
Den Thread Rechnen mit Variablen unter Batch habe ich gesehen und bin auch dem Link von Biber dort gefolgt, weitergebracht hat mich das leider nicht.
Mitglied: nullplan001
06.11.2005, aktualisiert 02.03.2016
Zunächst einmal kannst du die ganzen @ außer dem vor "echo off" löschen. Schon wird die Angelegenheit übersichtlicher. Und dann war da noch die Befehlserweiterung für WINNT. Lies dir mal bei Gelegenheit CMD /? durch.
Ich habe den Fehler aber schon ausgemacht: in der Schleife musst du den Befehl
01.
<tt>@set /a sum=%sum%+%%b</tt> in <tt>set /a sum=!sum!+%%b</tt>umwandeln
Und zwar deshalb: %sum% hat einen Wert. Dieser wird erst nach der Schleife aktualisiert. !sum! hat den Wert von %sum%, wird aber gleich in der Schleife aktualisiert. Wieso das so ist, fragst du besser Microsoft.
Bitte warten ..
Mitglied: Jansen
06.11.2005 um 12:35 Uhr
Hallo, danke für die Hilfe.

Lies dir mal bei Gelegenheit CMD /? durch.
Jo, hab ich schon, verstehe allerdings nicht genau, worauf du hinauswillst.

<tt>@set /a sum=%sum%+%%b</tt>
in <tt>set /a sum=!sum!+%%b</tt>
umwandeln.

Das produziert leider eine "Fehlender Operator"-Ausgabe.

Gruss,
Jansen
Bitte warten ..
Mitglied: Biber
06.11.2005, aktualisiert 02.03.2016
Moin Jansen,

Wieso das so ist, fragst du besser Microsoft.
...Biber fragen geht schneller..

Der Denkfehler ist folgender: Auch wenn Du die Anweisungen in Deiner FOR..IN..DO-Schleife noch so schön formatierst und in mehrere Zeilen auseinanderziehst - der CMD-Interpreter sieht und zieht sie als eine Zeile an.
Der liest sie zur Ausführungszeit en bloc ein und löst alle darin enthaltenen Variablen einmalig auf. Alle außer den FOR-Zählvariablen, die werden in jedem Schleifendurchlauf neu befüllt.
Du kannst dieses Verhalten beeinflussen/ändern über den Befehl
"setlocal EnableDelayedExpansion" .. verzögerte Variablen-Auflösung. Steht irgendwo in der Hilfe (SET/? oder CALL /?).

[Edit]
Wenn EnableDelayedExpansion nicht gesetzt ist, bekommst Du bei Verwendung der !var!-Syntax ein Problem:
>>Das produziert leider eine "Fehlender Operator"-Ausgabe.
[/Edit]

Oder aber.. ohne generelle DelayedExpansion geht es über das callen einer (Pseudo-)Subroutine.
Weil ich nicht so gut im Erklären bin, zeig ich das mal in einem Batchbeispiel.
01.
::-------snipp Summarize.bat 
02.
@echo off & setlocal 
03.
goto skipProsa 
04.
Die nächste Findstr-Zeile ist natürlich nur bei mir beim Testen sinnvoll. 
05.
Unten nach dem "goto :eof" stehen Deine Beispielzeilen (wie in der tmp.log). 
06.
Ich schreibe alle Zeilen, die mit "Wert:" beginnen, irgendwohin. 
07.
Bei Dir könnte dort stehen findstr /b "Wert:" c:\tmp.log>%NurWerte% 
08.
:SkipProsa 
09.
Set "NurWerte=%temp%\NurZeilenMitWertBeginnend.txt" 
10.
findstr /b "Wert:" Summarize.bat>%NurWerte% 
11.
Echo Die Werte: 
12.
Type %NurWerte% 
13.
Echo ----- 
14.
Call :Variante1 
15.
Call :Variante2 
16.
Call :Variante3 
17.
goto :eof 
18.
-----Ende des Haupt-Batches 
19.
 
20.
:Variante1 
21.
Echo Variante1) sum wird in EINER FOR..IN..DO..Zeile addiert 
22.
set /a sum=0  
23.
for /F "tokens=1,2" %%a in (%NurWerte%) do (      
24.
   if "%%a"=="Wert:" (  
25.
     if NOT "%%b"=="0" (  
26.
        set /a sum=%sum%+%%b  
27.
        echo ZwSum=%sum% ZwWert=%%b  
28.
        ) ) )  
29.
echo EndSum=%sum% 
30.
Goto :eof 
31.
----Ende :Variante1 
32.
---- 
33.
:Variante2 
34.
Echo. 
35.
Echo Variante2) sum wird in einem call:-Block addiert 
36.
set /a sum=0  
37.
for /F "tokens=1,2" %%a in (%NurWerte%) do call :Sum2 %%a %%b 
38.
echo EndSum=%sum% 
39.
goto :eof 
40.
----Ende :Variante2... ruft den Block ":sum2" 
41.
---- 
42.
:sum2 
43.
   if "%1"=="Wert:" (  
44.
     if NOT "%2"=="0" (  
45.
        set /a sum=%sum%+%2  
46.
        echo ZwSum=%sum% ZwWert=%2   
47.
        ) ) )  
48.
Goto :eof 
49.
----Ende :Sum2-"Subroutine" 
50.
------- 
51.
:Variante3 
52.
Echo. 
53.
Echo Variante3) ...etwas schlankere Version von Variante2 
54.
set /a sum=0  
55.
for /F "tokens=2" %%a in (%NurWerte%) do call :Sum3 %%a 
56.
echo EndSum=%sum% 
57.
goto :eof 
58.
----Ende :Variante3... ruft den Block ":sum3" 
59.
---- 
60.
:sum3 
61.
set /a sum+=%1  
62.
echo ZwSum=%sum% ZwWert=%1   
63.
Goto :eof 
64.
----Ende :Sum3-"Subroutine" 
65.
 
66.
Wert: 10  
67.
blabla bleh strunz  
68.
Wert: 0  
69.
Sülz di bülz  
70.
Wert: 13  
71.
blubber blub göbel dum  
72.
Wert: 26 
73.
-------snapp Summarize.bat
Der Output dieses Schnipsels:
01.
Summarize.bat 
02.
Die Werte: 
03.
Wert: 10 
04.
Wert: 0 
05.
Wert: 13 
06.
Wert: 26 
07.
----- 
08.
Variante1) sum wird in EINER FOR..IN..DO..Zeile addiert 
09.
ZwSum=0 ZwWert=10 
10.
ZwSum=0 ZwWert=13 
11.
ZwSum=0 ZwWert=26 
12.
EndSum=26 
13.
 
14.
Variante2) sum wird in einem call:-Block addiert 
15.
ZwSum=0 ZwWert=10 
16.
ZwSum=10 ZwWert=13 
17.
ZwSum=23 ZwWert=26 
18.
EndSum=49 
19.
 
20.
Variante3) ...etwas schlankere Version von Variante2 
21.
ZwSum=10 ZwWert=10 
22.
ZwSum=10 ZwWert=0 
23.
ZwSum=23 ZwWert=13 
24.
ZwSum=49 ZwWert=26 
25.
EndSum=49
Wenn das Deiner Meinung nach verständlich genug ist, hänge ich das nachher um als Tutorial.

Grüße
Biber
Bitte warten ..
Mitglied: Jansen
06.11.2005 um 15:26 Uhr
Danke!

Das Setzen von EnableDelayedExpansion funktioniert, und diese Variante werde ich auch verwenden (oder spricht etwas dagegen?).

Aber danke auch für die Alternativen, da habe ich wieder mehr gelernt als ursprünglich erhofft.
Bitte warten ..
Mitglied: Biber
06.11.2005, aktualisiert 02.03.2016
Moin Jansen,
ich habe auch in meiner CMD-"Workbench" immer das "EnableDelayedExpansion" gesetzt. Geht ja auch per Registry oder per AutoRun-Batch.
Kann aber seine Tücken haben, da ja nun alles zwischen zwei Ausrufungszeichen als Variable gnadenlos aufgelöst wird.
Dafür habe ich in meinem Workshop Batch for Runaways - Part II - Ein bisschen Handwerkszeug ein Beispiel, wo das in die Grütze geht. Wenn man/frau diesen Fall im Hinterkopf hat, ist es kein Problem.

Grüße
Frank / der Biber aus Bremen
Bitte warten ..
Mitglied: Jansen
06.11.2005 um 22:12 Uhr
Hmm ja, da werde ich die Auswertung wohl lieber per externem Batch erledigen, anstatt EDE direkt in das meterlange Backup-Script einzubauen.
Nochmals Danke für dein geduldiges Erklären!

Gruss,
Jansen
Bitte warten ..
Mitglied: Biber
07.11.2005, aktualisiert 02.03.2016
Na ja, Jansen,
ausreden wollte ich es Dir ja auch nicht.. nur die Tücken des Objekts aufzeigen.

In Deinem Fall kannst Du natürlich auch irgendwo in Deinem meterlangen Backup-Skript
(soll ich Dir das mal ein bisschen zusammendampfen? *gg)
noch einen kleinen 3-Zeilen Call-Block namens "getSumme" einbauen... ["set /a sum=0" muss vorher erfolgen]
01.
.. 
02.
:getSumme 
03.
setlocal EnableDelayedExpansion & set "NurWerte=c:\tmp.log" 
04.
for /F "tokens=2" %%a in (%NurWerte%) do set /a sum=!sum!+%%a 
05.
EndLocal & goto :eof 
06.
...
...hat ja schon einen gewissen Charme und würde ich wohl auch so machen.
Dann hast Du das "EnableDelayedExpansion" nur in diesem kleinen Block (durch "EndLocal" wieder auf vorherigen Stand gesetzt).

Andererseits .. ohne das DelayedExpansion-Feature hättest Du in Deinem Code eine Batch-Zeile mehr..was soll der Geiz?
Selbst meine Oneliner belegen auf manchen Festplatten 16.384 Bytes, obwohl keine Hundert Zeichen drin stehen.
Kannst also ruhig ein, zwei Zeilen mehr reinschreiben - kostet das Gleiche.

Stressarmen Wochenanfang
Biber
Bitte warten ..
Neuester Wissensbeitrag
Windows 10

Powershell 5 BSOD

(8)

Tipp von agowa338 zum Thema Windows 10 ...

Ähnliche Inhalte
Batch & Shell
gelöst Variablen Zusammenbauen 2.0 ( Batch ) (6)

Frage von clragon zum Thema Batch & Shell ...

Batch & Shell
gelöst FOR Loop Variablen ( Batch ) (2)

Frage von clragon zum Thema Batch & Shell ...

Batch & Shell
gelöst Grosses Variablen Problem ( Batch) (30)

Frage von clragon zum Thema Batch & Shell ...

Batch & Shell
Batch zum bearbeiten mehrerer CSV (3)

Frage von Matzus87 zum Thema Batch & Shell ...

Heiß diskutierte Inhalte
Windows Tools
gelöst Aussendienst Datensynchronisierung (12)

Frage von lighningcrow zum Thema Windows Tools ...

Windows Server
Suche passender Treiber (12)

Frage von stolli zum Thema Windows Server ...

Peripheriegeräte
Wlan stört Funkmaus (11)

Frage von Falaffel zum Thema Peripheriegeräte ...

Peripheriegeräte
gelöst USB Festplatte verliert Laufwerksbuchstabe (9)

Frage von cese4321 zum Thema Peripheriegeräte ...