Batch Zählenwennfunktion in txt einfügen

Dave1701

Cadet 1st Year
Registriert
Sep. 2016
Beiträge
13
Moin zusammen,

ich habe ein Problem. Und zwar möchte ich mehrere .xlsx Dateien in .csv umwandeln und diese .csv dann in eine .txt Datei zusammenführen (Grund ist eine Weiterverarbeitung mit einem anderen Tool).
Das Vorgehen funktioniert bisher einwandfrei.
Leider kann das Zieltool eine bestimmte, aber für mich wichtige, Aussage nicht konstruieren:
Ich möchte wissen, wie oft die Werte in Spalte A in der Datei vorkommen.

Da es sich um mehrere Millionen Datenzeilen handelt, kommt eine Verabreitung direkt in Excel per VBA nicht in Frage.
Weiterhin besteht das Problem, dass manche Dateien 27 Spalten, andere 30 haben (aber mindestens immer 27).

Ein kleines Beispiel:
Spalte A - Spalte B - Spalte C
Name - Adresse - Telefonnummer
Peter - Adresse1 - 0815
Peter - Adresse1 - 1234
Karsten - Adresse2 - 5678
Helmut - Adresse3 - 3456
Helmut - Adresse3 - 2958
Helmut - Adresse3 - 1057

In .csv würden die Daten natürlich mit ; getrennt dastehen.

Meine Überlegung jetzt:
Nach dem Einfügen in eine Gesamt .txt der Daten, möchte ich in jede Zeile (am besten vor "Name") die Anzahl der jeweiligen Namen schreiben:
Name;Adresse;Telefonnummer
2;Peter;Adresse1;0815
2;Peter;Adresse1;1234
1;Karsten;Adresse2;5678
3;Helmut;Adresse3;3456
3;Helmut;Adresse3;2958
3;Helmut;Adresse3;1057

Jetzt habe ich mehrere Codeschnipsel gefunden, einmal um den Dateiinhalt wiederzugeben, einmal um die Anzahl der Zeichen innerhalb einer Textdatei zu zählen, jedoch nicht genau das, was ich eigentlich möchte.
Eine direkte Übergabe des Names an eine Zählfunktion die Zeile für Zeile durchgeht und vor dem Name die Anzahl schreibt. Leider bin ich in Batch auch nicht wirklich zuhause, sodass ich viele Sachen nicht wirklich verstehe :D

Eine Alternative die mir gerade einfällt, man könnte die Namen auch herauskopieren, in eine neue .txt Datei schreiben, anschließend zählen und die Anzahl in die neue .txt Datei einfügen und die Duplikate entfernen.
Leider weiß ich nicht was "einfacher" ist.

Ich hoffe ihr könnt mir helfen.

Grüße,
David
 
Ich nehme mal an Du arbeitest auf Windows, richtig? Wie ist es denn mit den Dateien, die mehr als 27 Zeilen haben: sind die zusätzlichen Informationen ausschließlich in den zusätzlichen Spalten, oder sind dann die ersten 27 Spalten nicht immer gleich belegt? Mit Batchscripten kenne ich mich leider auch nicht aus, dafür aber mit awk ein bisschen, für das was Du brauchst würde es denke ich reichen.
 
Rage schrieb:
Ich nehme mal an Du arbeitest auf Windows, richtig? Wie ist es denn mit den Dateien, die mehr als 27 Zeilen haben: sind die zusätzlichen Informationen ausschließlich in den zusätzlichen Spalten, oder sind dann die ersten 27 Spalten nicht immer gleich belegt? Mit Batchscripten kenne ich mich leider auch nicht aus, dafür aber mit awk ein bisschen, für das was Du brauchst würde es denke ich reichen.

Richtig, Windows 7 um genau zu sein.

Die ersten 27 Spalten sind (fast) immer gefüllt, kann durchaus vorkommen, dass manche Zellen keinen Wert haben.
Würde man mein o.g. Beispiel um 1 Spalte ändern, nehmen wir jetzt mal "Vorgangsnummer" bzgl. eines Bestellvorganges anstelle der Telefonnummer, dann kann ja 1 Name mehrmals vorkommen, je nachdem wie oft derjenige etwas bestellt.
Die Spalten "Name" und "Vorgangsnummer" sind in meinen Daten immer gefüllt. Die restlichen Spalten sind nur Zusatzinformationen und zum Zählen nicht relevant.

Ich hoffe ich habe deine Frage richtig verstanden :D
 
Ich meinte eigentlich, ob in Spalte x mit 1 <= x <= 27 immer dieselbe Art von Informationen stehen. Dein Problem ist so wie ich das sehe kein zu schwieriges, wenn sich niemand mehr meldet könnte ich Dir ein awk-Skript schreiben, das Dir Deine Daten durchwühlt. Bräuchtest aber sowas wie cygwin dafür, Linux in der Windows-Konsole fällt für Dich flach wegen Windows 7 soweit ich weiß.
 
Rage schrieb:
Ich meinte eigentlich, ob in Spalte x mit 1 <= x <= 27 immer dieselbe Art von Informationen stehen. Dein Problem ist so wie ich das sehe kein zu schwieriges, wenn sich niemand mehr meldet könnte ich Dir ein awk-Skript schreiben, das Dir Deine Daten durchwühlt. Bräuchtest aber sowas wie cygwin dafür, Linux in der Windows-Konsole fällt für Dich flach wegen Windows 7 soweit ich weiß.

Moin, sorry am Wochenende keine Zeit gehabt :/
Cygwin kenne ich nicht. Nach ersten Informationen laut Google, muss das aber installiert werden, oder? Diese Möglichkeit habe ich leider nicht bei der Arbeit :/
 
Kann man mit Batch machen, würde aber bei mehreren Millionen Datensätzen stundenlang rechnen. Ich würde auch awk für Windows oder Powershell vorschlagen. Problem: awk muss zwar nicht installiert aber kopiert und ausführbar sein und Powershell wird von vielen Admins wegen dessen "mächtiger" Möglichkeiten im System rumzupfuschen abgeschaltet.

PS: Batch kann nur Zeilen bis maximal 8191 Zeichen verarbeiten, wenn deine Textdatei mehr hat, wird der Rest einfach abgeschnitten.
 
Zuletzt bearbeitet: (PS)
Endoro schrieb:
* Überflüssiges Zitat editiert! *

Danke für deinen Post. Das mit Batch wusste ich nicht. D.h. wenn ich mittels Batch und "findstr" oder "find" die .txt bereinigen möchte, macht er das nur für die ersten 8191 Zeichen machen? Ist mir bisher nicht aufgefallen, da die Dateien vollständig bereinigt waren.

Versuche das ganze jetzt mit AWK, hoffe ich finde einschlägige Literatur oder Beispiele im Netz.
Solange ich Programme nicht installieren muss, ist das kein Problem bei der Arbeit. Glaube aber, dass PowerShell wirklich abgeschaltet ist.

Danke für eure Mühe.
 
Zuletzt bearbeitet von einem Moderator:
Dave1701 schrieb:
Batch und "findstr" oder "find" die .txt bereinigen möchte
"Find" und "findstr" sind noch mal sehr viel eingeschränkter, die würde ich gar nicht verwenden. Was ich meine, ist das Einlesen der Textdatei mit einer "for /f"-Schleife, die Bearbeitung mit Zeichenkettenfunktionen und die Ausgabe mittels "echo".

In Awk ist das Ganze ziemlich einfach:
- ";" als Feldtrenner angeben
- Datei einlesen und ein Array mit den Namen und deren Häufigkeiten erstellen
- am Anfang ein Feld mit der passenden Häufigkeit einfügen und ausgeben
Könnte vielleicht sogar ein Einzeiler werden.

Als weitere Alternativen sind natürlich Excel selbst zu nennen oder ein beliebiges Datenbankprogramm.
Ergänzung ()

Es geht tatsächlich als Einzeiler, getestet auf OS X mit GNU Awk 4.1.1, die Quotierung bei Windows kann anders sein:

Code:
awk -F";" '{if (NR == 1) {header = "Freq;" $0} else {d[NR]=$0; n[$1]++} next}; END {print (header); for (a in d) {$0 = d[a]; printf("%d;%s\n", n[$1], d[a])}}' in.csv  > out.csv

Anmerkung: bei awk-Arrays darf man sich definitionsgemäß nicht darauf verlassen, dass bei der "for (a in d)"-Konstruktion die Records in der gleichen Reihenfolge wieder ausgegeben werden, wie sie eingegeben wurden. Praktisch hab ich aber nie ein anderes Verhalten feststellen können und auf das richtige Ergebnis der Datensätze hätte das hier auch keinen Einfluß.
 
Zuletzt bearbeitet: (ein Paar "{}" zu viel)
Endoro schrieb:
Code:
awk -F";" '{if (NR == 1) {header = "Freq;" $0} else {d[NR]=$0; n[$1]++} next}; END {print (header); for (a in d) {$0 = d[a]; printf("%d;%s\n", n[$1], d[a])}}' in.csv  > out.csv

Könntest du vielleicht deine Zeile kurz beschreiben?
Verstehe, bzw. meine zu Verstehen, dass du d (Spalte 4) als Zählspalte benutzt, oder? Wenn ich Spalte 2 zählen wollen würde, müsste da
Code:
... else {b[NR]=$0}; n[$1]++}; END
oder?
Den Bezug der Zählspalte auf die Vorkommen nimmst du mit "for (a in d) ...." vor, oder?
Und per
Code:
 n[$1], d[a]
gibst du die Reihenfolge so aus, dass zuerst die Anzahl der Vorkommen und danach der Rest ausgegeben wird, oder?
 
@Dave1701 ich habe das mit der von dir vorgeschlagenen Beispieldatei getestet. Das Sitzungsprotokoll sieht also folgendermaßen aus:
Code:
$ cat in.csv
Name;Adresse;Telefonnummer
Peter;Adresse1;0815
Peter;Adresse1;1234
Karsten;Adresse2;5678
Helmut;Adresse3;3456
Helmut;Adresse3;2958
Helmut;Adresse3;1057
$ awk -F";" '{if (NR == 1) {header = "Freq;" $0} else {d[NR]=$0; n[$1]++} next}; END {print (header); for (a in d) {$0 = d[a]; printf("%d;%s\n", n[$1], d[a])}}' in.csv
Freq;Name;Adresse;Telefonnummer
2;Peter;Adresse1;0815
2;Peter;Adresse1;1234
1;Karsten;Adresse2;5678
3;Helmut;Adresse3;3456
3;Helmut;Adresse3;2958
3;Helmut;Adresse3;1057
$
 
@Endoro

Kennst du vielleicht Seiten in dem man etwas über AWK erfahren kann? Ich scheitere schon daran ein AWK Statement auszuführen -.-
 
Eigentlich musst du dich um die Syntax nicht weiter kümmern, wenn du awk.exe (oder gawk.exe) in einem Ordner gespeichert hast, der in der "PATH"-Umgebungsvariablen von Windows aufgeführt ist. Dann musst du nur noch eine Eingabeaufforderung ("DOS-Fenster") über die Tastenkombination "Windows-X" aufzurufen, zum Ordner mit deinen Dateien mit "cd ..." manövrieren und die von mir gepostete Eingabezeile reinschreiben oder pasten. Wenn es zu Syntax-Fehlern kommt, liegt das meist an der unterschiedlichen Quotierung, das sind " und ' in der Eingabeaufforderung von Windows, dann melde dich noch mal.

Eine sehr gute Übersicht über awk findest du hier.
 
So, habe den Code jetzt soweit, dass es keine Fehlermeldung mehr gibt. Der einzige Part, der noch nicht ohne Fehlermeldung funktioniert, ist der "printf"-Part. Bekomme da jedes Mal einen Syntax-Fehler.
Mein bisheriger Code:
Code:
gawk -F ";" "{if (NR==1) {header = "freq"; $0} else {d[NR]=$0; n[$1]++} next}; END {print (header); for (a in c) {$0 = c[a]}}" in.csv > out.csv

Edit 19.09.2015 21:04 Uhr:
Habe jetzt diverse Sache als Formatierung ausprobiert bei printf.
Liegt wohl am "%"-Zeichen. Gebe ich z.B. "-s" an, kommen 0 Nullen zurück, jedoch die gleiche Anzahl 0 wie Zeilen vorhanden.
 
Zuletzt bearbeitet:
Hi, sorry dass ich gestern nicht mehr reingeschaut habe, muss mich mal sehr bei Endoro bedanken, cool dass es noch andere Menschen gibt die awk kennen und hier im Forum helfen! Bei Deinem aktuellen Problem kann ich Dir leider nicht mehr helfen, wenn Du allerdings jetzt die doppelten Zeilen aus der Ausgabe entfernen willst geht das mit meinem Lieblings-awk-Einzeiler:

Code:
gawk '!a[$0]++' out.csv > aus.csv
 
@Endoro Batch performt sicherlich eher schlecht, stundenlang für eingie Millionen Zeilen wäre aber mMn trotzdem übertrieben.
Das Zählen und schreiben in eine extra Datei, also die Alternative, sofern ich die richtig verstanden habe, dauert mit folgender Batchlösug bei mir ca. 6s für 300 000 Zeilen:
Code:
@echo off
cd "%~dp1"
setlocal
for /F "tokens=1 delims=;" %%a in (%~nx1) do (
 set /a COUNTER_%%a=COUNTER_%%a+1
)
if exist output_%~n1.txt del output_%~n1.txt
set | for /F "tokens=2,3 delims=_= " %%b in ('find "COUNTER"') do echo %%b %%c >>output_%~n1.txt
endlocal
Ich kann mir vorstellen, dass die awk Varianten da schon um einiges schneller sind. Bei mehreren Millionen Zeilen wird sich das schon bemerkbar machen.
 
Dave1701 schrieb:
So, habe den Code jetzt soweit, dass es keine Fehlermeldung mehr gibt. Der einzige Part, der noch nicht ohne Fehlermeldung funktioniert, ist der "printf"-Part. Bekomme da jedes Mal einen Syntax-Fehler.

Bei mir funktioniert der Code unverändert auch unter Windows. Hier ein Foto der Sitzung:



Dave1701 schrieb:
Liegt wohl am "%"-Zeichen. Gebe ich z.B. "-s" an, kommen 0 Nullen zurück, jedoch die gleiche Anzahl 0 wie Zeilen vorhanden.
Nein, an den %-Zeichen liegt es nicht, wenn du den Code direkt an der Eingabeaufforderung eingibst. Wenn du ihn allerdings von einer Batch-Datei aus aufrufst müssen die Prozentzeichen verdoppelt werden.

PS:
@simpsonsfan: Dein Script tut nicht das, was der TE imo erwartet.
 
Zuletzt bearbeitet: (PS)
@Endoro Ja, mein Skript entspricht wohl nicht ganz dem, was Dave1701 sucht. Ich persönlich hatte die Alternativmöglichkeit zunächst so aufgefasst.

Ich hab mir übrigens zum Test auch awk für Windows geladen. Unter Windows 10 erhalte ich mit deinem Code auch einen Syntaxfehler.
 
@simpsonsfan: Hast du den Code an der Eingabeaufforderung eingegeben oder als Batch aufgerufen? In einer Batch sähe er so aus:
Code:
@echo on & setlocal
awk -F";" '{if (NR == 1) {header = "Freq;" $0} else {d[NR]=$0; n[$1]++} next}; END {print (header); for (a in d) {$0 = d[a]; printf("%%d;%%s\n", n[$1], d[a])}}' in.csv

Mach doch mal ein Bildschirmfoto des Ablaufs. Welches awk verwendest du?
 
Ich habe gawk for Windows 3.1.6-1 verwendet, von http://gnuwin32.sourceforge.net/packages/gawk.htm

Aufruf ganz normal aus der cmd heraus, nicht als Batch.
awk syntax error.jpg
 
Zurück
Oben