wemdas
Goto Top

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.

Content-Key: 136055

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

Printed on: April 19, 2024 at 01:04 o'clock

Member: Snowman25
Snowman25 Feb 16, 2010 at 10:09:19 (UTC)
Goto Top
Member: wemdas
wemdas Feb 16, 2010 at 10:33:06 (UTC)
Goto Top
sortieren muss nicht unbedingt sein, vielmehr gruppieren oder zusammenfassen
Member: bastla
bastla Feb 16, 2010 at 13:29:33 (UTC)
Goto Top
Hallo wemdas!

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)  
)
[Edit] Parameter "/b" nachgereicht (falls nicht alle Werte die selbe Stellenanzahl haben sollten) [/Edit]

Grüße
bastla
Member: wemdas
wemdas Feb 17, 2010 at 19:20:41 (UTC)
Goto Top
Hallo bastla,

hervorragend, hat auf Anhieb funktioniert.
Großes Kompliment, schönen Abend und Danke.


Gruß
wemdas
Member: Biber
Biber Feb 17, 2010 at 20:00:41 (UTC)
Goto Top
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:
@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
Member: bastla
bastla Feb 17, 2010 at 22:20:08 (UTC)
Goto Top
@Biber
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 face-wink) ...

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) ...
Member: Biber
Biber Feb 18, 2010 at 07:41:25 (UTC)
Goto Top
Moin bastla,

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.

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... face-wink

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...

Grüße
Biber