Per batch gruppieren und zählen
Hallo zusammen,
ein Lob an dieses Forum, hab' mir bisher schon sehr viele Informationen aus diesem Forum gezogen.
Nun habe ich allerdings ein Problem, bei dem ich noch nicht weitergekommen bin.
Meine bisherigen Versuche, leider erfolglos:
@echo off & setlocal
set /a ANZ=0
for /f %%i in ('findstr /G:c:\eze\Anz_Ger2.txt C:\eze\Anz_Ger3.txt') do set /a ANZ+=1
echo %ANZ%
pause
oder
@echo off & setlocal
for /f "tokens=3" %%l in ('find /C " " C:\eze\Anz_Ger3.txt') do set ANZ=%%l
echo %ANZ%
pause
So sieht meine Eingangsgröße aus
(Datei "c:\eze\Anz_Ger3.txt", die aber jeden Tag eine andere Anzahl von 0501, 0502, ... liefern kann und auch nicht jeden Tag immer 0501, 0502 und 1502 hat - manchmal fehlt z.B. 1502):
0501
0501
0501
0502
0502
1502
1502
1502
1502
Nun soll als Ergebnis erscheinen:
0501 Anzahl: 3
0502 Anzahl: 2
1502 Anzahl: 4
Danke schon mal an die Mitglieder dieses Foruums. Schön, dass es so etwas gibt.
ein Lob an dieses Forum, hab' mir bisher schon sehr viele Informationen aus diesem Forum gezogen.
Nun habe ich allerdings ein Problem, bei dem ich noch nicht weitergekommen bin.
Meine bisherigen Versuche, leider erfolglos:
@echo off & setlocal
set /a ANZ=0
for /f %%i in ('findstr /G:c:\eze\Anz_Ger2.txt C:\eze\Anz_Ger3.txt') do set /a ANZ+=1
echo %ANZ%
pause
oder
@echo off & setlocal
for /f "tokens=3" %%l in ('find /C " " C:\eze\Anz_Ger3.txt') do set ANZ=%%l
echo %ANZ%
pause
So sieht meine Eingangsgröße aus
(Datei "c:\eze\Anz_Ger3.txt", die aber jeden Tag eine andere Anzahl von 0501, 0502, ... liefern kann und auch nicht jeden Tag immer 0501, 0502 und 1502 hat - manchmal fehlt z.B. 1502):
0501
0501
0501
0502
0502
1502
1502
1502
1502
Nun soll als Ergebnis erscheinen:
0501 Anzahl: 3
0502 Anzahl: 2
1502 Anzahl: 4
Danke schon mal an die Mitglieder dieses Foruums. Schön, dass es so etwas gibt.
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 136055
Url: https://administrator.de/forum/per-batch-gruppieren-und-zaehlen-136055.html
Ausgedruckt am: 18.04.2025 um 15:04 Uhr
7 Kommentare
Neuester Kommentar
hallo @wemdas,
zum sortieren schaust du mal hier: Zahlen aus einer .txt-Datei sortieren und erneut abspeichern
zum sortieren schaust du mal hier: Zahlen aus einer .txt-Datei sortieren und erneut abspeichern
Hallo wemdas!
Etwa so:
[Edit] Parameter "/b" nachgereicht (falls nicht alle Werte die selbe Stellenanzahl haben sollten) [/Edit]
Grüße
bastla
Etwa so:
@echo off & setlocal
set "Ein=D:\Daten.txt"
set "Aus=D:\Auswertung.txt"
type nul>"%Aus%"
for /f "usebackq delims=" %%i in ("%Ein%") do (
findstr /b /c:"%%i Anzahl:" "%Aus%">nul||(for /f %%a in ('find /c "%%i" ^<"%Ein%"') do >>"%Aus%" echo %%i Anzahl: %%a)
)
Grüße
bastla
Moin wemdas,
noch mal der Vollständigkeit halber...
bastlas Schnipsel ist ein funktionierender Ansatz speziell für den Fall, dass die Daten unsortiert vorliegen.
Allerdings hat die Kürze des Codes und die universelle Einsetzbarkeit unter Umständen einen Nachteil..
Für jede gatesverdammte Zeile in der Eingabedatei müssen zwei externe Programme aufgerufen werde (Find.exe und FindStr.exe).
Und 100000 Zeilen mit einem FOR/F-Konstrukt durchwackelt werden, wenn denn 100000 zeilen drin wären in der Ein-Datei.
Die klassische Mimik der Gruppenverarbeitung würde ja anders ansetzen, nämlich
a) falls nicht ohnehin gegeben, sicherstellen, dass die zu lesende Datei nach Gruppenwechsel-Begriffen sortiert ist (so wie in deiner Darstellung ganz oben)
b) alle 100000 Zeilen durchwackeln meinetwegen mit einer FOR/F-Anweisung
c) bei jedem Gruppenwechsel das Zwischenergebnis dieser Gruppe rausschreiben.
FALLS also deine Ein-Liste sortiert vorliegen sollte, dann sollte es so konservativer, aber flotter gehen:
[hier im Beispiel unterstellt: eine Ein-Datei namens "wemdas.txt", sortiert, im aktuellen Verzeichnis; Ergebnis auf dem Monitor]
Ginge also auch ohne 2x 100000 zusätzliche Find/FindStr-Aufrufe.
Grüße
Biber
noch mal der Vollständigkeit halber...
bastlas Schnipsel ist ein funktionierender Ansatz speziell für den Fall, dass die Daten unsortiert vorliegen.
Allerdings hat die Kürze des Codes und die universelle Einsetzbarkeit unter Umständen einen Nachteil..
Für jede gatesverdammte Zeile in der Eingabedatei müssen zwei externe Programme aufgerufen werde (Find.exe und FindStr.exe).
Und 100000 Zeilen mit einem FOR/F-Konstrukt durchwackelt werden, wenn denn 100000 zeilen drin wären in der Ein-Datei.
Die klassische Mimik der Gruppenverarbeitung würde ja anders ansetzen, nämlich
a) falls nicht ohnehin gegeben, sicherstellen, dass die zu lesende Datei nach Gruppenwechsel-Begriffen sortiert ist (so wie in deiner Darstellung ganz oben)
b) alle 100000 Zeilen durchwackeln meinetwegen mit einer FOR/F-Anweisung
c) bei jedem Gruppenwechsel das Zwischenergebnis dieser Gruppe rausschreiben.
FALLS also deine Ein-Liste sortiert vorliegen sollte, dann sollte es so konservativer, aber flotter gehen:
@echo off & setlocal
Set /p ThisOne=<wemdas.txt
echo Start %thisOne%
Set /a CountNow=0
For /F %%i in (Wemdas.txt) do call:countItem %%i
:CountItem
If "%thisOne%" == "%1" Set /a "CountNow+=1" & goto :eof
If %countNow% GTR 0 (
Echo %ThisOne% Anzahl %CountNow%
Set /a "CountNow=1"
Set "ThisOne=%1"
)
[hier im Beispiel unterstellt: eine Ein-Datei namens "wemdas.txt", sortiert, im aktuellen Verzeichnis; Ergebnis auf dem Monitor]
Ginge also auch ohne 2x 100000 zusätzliche Find/FindStr-Aufrufe.
Grüße
Biber
@Biber
Deine Einwände sind natürlich völlig richtig - ein Detail wäre allerdings zu korrigieren:
) ...
Nixdestotrotz ist es (bei entsprechend großer Zeilenanzahl) wahrscheinlich auch für unsortierte Daten effizienter, eine sortierte Temp-Datei zu erzeugen und diese auf die von Dir beschriebene Art auszuwerten.
Wäre übrigens eine Schleife mit "delayedExpansion" (und damit ohne Notwendigkeit des Unterprogrammaufrufes) noch schneller?
Grüße
bastla
P.S.: Bei "Gruppenverarbeitung" werde ich ein wenig nostalgisch - derartiges hab' ich erstmals in meinen BASIC-Anfängen 1979 auf einer PDP-8 geschrieben (und auf Lochstreifen gespeichert) ...
Deine Einwände sind natürlich völlig richtig - ein Detail wäre allerdings zu korrigieren:
Für jede gatesverdammte Zeile in der Eingabedatei müssen zwei externe Programme aufgerufen werde (Find.exe und FindStr.exe).
"Findstr.exe
" wird tatsächlich für jede einzelne Zeile benötigt, "Find.exe
" allerdings für jeden vorkommenden Wert nur einmal (aber natürlich immer noch oft genug Nixdestotrotz ist es (bei entsprechend großer Zeilenanzahl) wahrscheinlich auch für unsortierte Daten effizienter, eine sortierte Temp-Datei zu erzeugen und diese auf die von Dir beschriebene Art auszuwerten.
Wäre übrigens eine Schleife mit "delayedExpansion" (und damit ohne Notwendigkeit des Unterprogrammaufrufes) noch schneller?
Grüße
bastla
P.S.: Bei "Gruppenverarbeitung" werde ich ein wenig nostalgisch - derartiges hab' ich erstmals in meinen BASIC-Anfängen 1979 auf einer PDP-8 geschrieben (und auf Lochstreifen gespeichert) ...
Moin bastla,
Di Krux liegt ja im Erkennen des Gruppenwechsels.. ein Gruppenwechsel in oben beschriebenen Sinn wird erkannt, wenn sich der neue Gruppenbegriff unterscheidet vom zuletzt "gemerkten (die Variable %thisOne% in der Skizze.
Dann wird, bei einem neuen %thisOne%, eine Summenzeile für das bisherige %thisOne& geschrieben.
Guter Plan, allerdings würde das für den letzten Gruppenwechselbegriff KEIN Gruppenwechselbegriff "gemerkt".
Diese kleine Klippe umgehe ich dadurch, dass (ganz unauffällig, wie ich hoffte) zwischen Zeile 06 und Zeile 08 am Ende des eigentlichen Batches und vor Beginn des "Unterprogramms" ein "goto :eof" fehlt.
In diesem Fall bewusst - nach dem Ende des Hauptbatches werden noch einmal mehr die Codezeilen durchlaufen, die eigentlich das Unterprogramm ":CountItem" darstellen.
Wie geschrieben... diese krumme Programmierung bekomme ich ohne CALL-Aufruf und mit DelayedExpansion nicht so unauffällig hin...
Grüße
Biber
Zitat von @bastla:
Wäre übrigens eine Schleife mit "delayedExpansion" (und damit ohne Notwendigkeit des Unterprogrammaufrufes) noch schneller?
Ja nee.... da gibt es ein Detail in dem oben skizzierten Prozessablauf, auf den ich eigentlich gar nicht besonders eingehen wollte und den ich ohne Unterprogrammaufruf gar nicht so unauffällig hinbekommen hätte.Wäre übrigens eine Schleife mit "delayedExpansion" (und damit ohne Notwendigkeit des Unterprogrammaufrufes) noch schneller?
Di Krux liegt ja im Erkennen des Gruppenwechsels.. ein Gruppenwechsel in oben beschriebenen Sinn wird erkannt, wenn sich der neue Gruppenbegriff unterscheidet vom zuletzt "gemerkten (die Variable %thisOne% in der Skizze.
Dann wird, bei einem neuen %thisOne%, eine Summenzeile für das bisherige %thisOne& geschrieben.
Guter Plan, allerdings würde das für den letzten Gruppenwechselbegriff KEIN Gruppenwechselbegriff "gemerkt".
Diese kleine Klippe umgehe ich dadurch, dass (ganz unauffällig, wie ich hoffte) zwischen Zeile 06 und Zeile 08 am Ende des eigentlichen Batches und vor Beginn des "Unterprogramms" ein "goto :eof" fehlt.
In diesem Fall bewusst - nach dem Ende des Hauptbatches werden noch einmal mehr die Codezeilen durchlaufen, die eigentlich das Unterprogramm ":CountItem" darstellen.
Wie geschrieben... diese krumme Programmierung bekomme ich ohne CALL-Aufruf und mit DelayedExpansion nicht so unauffällig hin...
P.S.: Bei "Gruppenverarbeitung" werde ich ein wenig nostalgisch - derartiges hab' ich ertmals in meinen
BASIC-Anfängen 1979 auf einer PDP-8 geschrieben (und auf Lochstreifen gespeichert) ...
Ja, auch ich kenne sowas auch noch in COBOL-Syntax und mit HOST-Steuerkarten...BASIC-Anfängen 1979 auf einer PDP-8 geschrieben (und auf Lochstreifen gespeichert) ...
Grüße
Biber