Diese Website existiert nur weil wir Werbung mit AdSense ausliefern.
Bitte den AdBlocker daher auf dieser Website ausschalten! Danke.

CSV Datei aufsplitten in mehrere Files

Alles rund um die verschiedenen Konsolen und shells sowie die Programmierung unter Linux

Moderator: Moderatoren

Flash
Member
Member
Beiträge: 210
Registriert: 24. Nov 2005, 17:54

CSV Datei aufsplitten in mehrere Files

Beitrag von Flash » 2. Apr 2017, 17:38

Hallo Leute,

ich hab eine CSV Datei mit folgendem Format

Code: Alles auswählen

"Unwichtiger Text"
"Unwichtiger Text"
"Spalte1","Typ","Spalte3","Spalte4"
"1234","TYP-A","Text","Anderes Zeug"
"1256","TYP-B","Text","Anderes Zeug"
"1333","TYP-C","Text","Anderes Zeug"
"6421","TYP-B","Text","Anderes Zeug"
"9898","TYP-A","Text","Anderes Zeug"
Frage 1
Ich möchte nun gern alle Zeilen die den TYP-A haben in eine Datei aussortieren, die mit TYP-B in eine andere Datei, die mit TYP-C in eine dritte.
Wie geht das?
Ich könnte eine Liste aller Werte die in der TYP Spalte auftreten können in einem extra Textfile bereit stellen.

Frage 2
Darauf Aufbauend habe ich dann aber den Bedarf, verschiedene Files die solche Inhalte haben in den Ergebnis Files zusammen zu führen.
Es gibt als 2 oder 10 solche CSV Files und die können alle Einträge von Typ TYP-A haben. Ich will das alle Einträge mit TYP-A aus allen Files in einem File zusammen geführt werden. Sortieren und auswerten kann ich dann mit den Tabellen-Kalkulationsprogrammen.

Werbung:
Benutzeravatar
framp
Moderator
Moderator
Beiträge: 4247
Registriert: 6. Jun 2004, 20:57
Wohnort: bei Stuttgart
Kontaktdaten:

Re: CSV Datei aufsplitten in mehrere Files

Beitrag von framp » 2. Apr 2017, 19:18

Dazu eignet sich grep perfekt. Voraussetzung: Der Text ,"TYP-A", usw kommt sonst nicht noch anders in den Dateien vor. Ansonsten muss man einen komplexeren regulären Ausdruck zusammenbauen. Ich denke aber so sollte es ausreichen.

Code: Alles auswählen

grep ',"TYP-A",' * > TYPA.csv
grep ',"TYP-B",' * > TYPB.csv
grep ',"TYP-C",' * > TYPC.csv

Gräfin Klara
Hacker
Hacker
Beiträge: 316
Registriert: 23. Jun 2008, 20:51

Re: CSV Datei aufsplitten in mehrere Files

Beitrag von Gräfin Klara » 2. Apr 2017, 19:20

Frage 1
Probiere das aus (ich habe es nicht getestet)

Code: Alles auswählen

#! /bin/bash

TPA="/tmp/type_a"
TPB="/tmp/type_b"
TPC="/tmp/type_c"

parse_type()
{
	 local arr ct=1 fn="$1"
	 while IFS= read -r; do
		 IFS=$','
		 arr=($REPLY)
		 printf "[%.3d] %s\n" "$ct" "$REPLY"
		 case "${arr[1]}" in
 		 "TYP-A")
	 			 printf "%s\n" "$REPLY" >> "$TPA"
	 			 ;;
		 "TYP-B")
	  			printf "%s\n" "$REPLY" >> "$TPB"
	  			;;
 		"TYP-C")
	 			 printf "%s\n" "$REPLY" >> "$TPC"
	  			;;
 	esac
	 ((ct++))
	 done < "$fn"
	 return 0
}

[ -f "$1" ] || exit 1
#rm -f "$TPA"
#rm -f "$TPB"
#rm -f "$TPC"
parse_type "$1"
exit 0
Abspeichern als z.B. test.sh

# test.sh "/path/das_noch_undecodierte_file"

Frage 2 verstehe ich nicht bzw. wird jemand anderer auflösen

Gruß
Gräfin Klara

Benutzeravatar
framp
Moderator
Moderator
Beiträge: 4247
Registriert: 6. Jun 2004, 20:57
Wohnort: bei Stuttgart
Kontaktdaten:

Re: CSV Datei aufsplitten in mehrere Files

Beitrag von framp » 2. Apr 2017, 19:36

Anbei eine noch kompaktere Version die gleich die Ausgabedateien automatisch für alle TYP-x erstellt :D

Code: Alles auswählen

for t in TYP-A TYP-B TYP-C; do echo "Creating $t.csv ...";egrep -E "[^,]+,\"$t\"," * > $t.csv; done

Gräfin Klara
Hacker
Hacker
Beiträge: 316
Registriert: 23. Jun 2008, 20:51

Re: CSV Datei aufsplitten in mehrere Files

Beitrag von Gräfin Klara » 2. Apr 2017, 19:42

framp hat geschrieben:
2. Apr 2017, 19:36
Anbei eine noch kompaktere Version die gleich die Ausgabedateien automatisch für alle TYP-x erstellt :D

Code: Alles auswählen

for t in TYP-A TYP-B TYP-C; do echo "Creating $t.csv ...";egrep -E "[^,]+,\"$t\"," * > $t.csv; done
HaHa, Ja, das ist kompakt

Flash
Member
Member
Beiträge: 210
Registriert: 24. Nov 2005, 17:54

Re: CSV Datei aufsplitten in mehrere Files

Beitrag von Flash » 2. Apr 2017, 20:16

Danke für die Antworten. Hier noch ein paar Infos und Fragen:

Frage 2 ist so zu verstehen, dass ich nicht nur ein eingabe-file habe sondern mehrere.
Ich glaube die Lösung sieht irgendwie so aus: (Pseudocode wobei irgendwie $datei1 und $datei2 übergeben werden)

Code: Alles auswählen

for t in Leerzeichen getrennte liste aller typen; 
do 
    echo "Creating $t.csv ...";
    echo "schreibe Header";
    grep "Spalte1" $datei1 > $t.csv;
    
    echo "schreibe zeilen aus datei 1";
    grep $t $datei1 >> $t.csv;
    
    echo "schreibe zeilen aus datei 2"; 
    grep $t $datei2 >> $t.csv;
done
Wie bekomme ich $datei1 bzw $datei2 übergeben? Ich bau mir gerade ein shell script was die Werte zusammen sammelt.

Flash
Member
Member
Beiträge: 210
Registriert: 24. Nov 2005, 17:54

Re: CSV Datei aufsplitten in mehrere Files

Beitrag von Flash » 2. Apr 2017, 20:23

Idealerweise ist das ganze nicht limitiert auf 2 dateien. Sondern 2..n dateien.


Flash
Member
Member
Beiträge: 210
Registriert: 24. Nov 2005, 17:54

Re: CSV Datei aufsplitten in mehrere Files

Beitrag von Flash » 2. Apr 2017, 20:45

Ah.... da ist ja ein kleines "*" im grep. Hab ich übersehen.

Ok, dann probier ich mal mein Script aus.

Flash
Member
Member
Beiträge: 210
Registriert: 24. Nov 2005, 17:54

Re: CSV Datei aufsplitten in mehrere Files

Beitrag von Flash » 2. Apr 2017, 21:03

Ok, habs ausprobiert. Es gibt noch ein kleines Problem mit dem "*" Modus.
Und zwar schreibt grep das >>FileName.typ:<< direkt vor die Grep ausgabe. Kann man das formatieren? z.B. dass statt dem : ein , verwendet wird (csv conform)


Flash
Member
Member
Beiträge: 210
Registriert: 24. Nov 2005, 17:54

Re: CSV Datei aufsplitten in mehrere Files

Beitrag von Flash » 2. Apr 2017, 21:44

Wenn ich das hier ausführe: foo@bar:~/Downloads$ grep Transaktionen *.txt > foobar.txt

dann sieht das resultat in foobar.txt so aus:

Code: Alles auswählen

report (10).txt:Transaktionen: 30								
report (11).txt:Transaktionen: 66
report (12).txt:Transaktionen: 27
report (13).txt:Transaktionen: 42
report (14).txt:Transaktionen: 37
report (15).txt:Transaktionen: 55
report (16).txt:Transaktionen: 55								
report (17).txt:Transaktionen: 76
report (18).txt:Transaktionen: 51
report (19).txt:Transaktionen: 75
report (1).txt:Transaktionen: 14
report (20).txt:Transaktionen: 76
report (21).txt:Transaktionen: 82
report (22).txt:Transaktionen: 112								
report (23).txt:Transaktionen: 113											Verkauf
report (24).txt:Transaktionen: 74
report (25)_020816-250816.txt:Transaktionen: 186									
report (25).txt:Transaktionen: 126
report (26).txt:Transaktionen: 142
report (27).txt:Transaktionen: 166
report (28).txt:Transaktionen: 167
report (29).txt:Transaktionen: 160
report (2).txt:Transaktionen: 12
report (30).txt:Transaktionen: 92									
report (31).txt:Transaktionen: 187
report (32).txt:Transaktionen: 236
report (33).txt:Transaktionen: 485
report (3).txt:Transaktionen: 22
report (4).txt:Transaktionen: 15
report (5).txt:Transaktionen: 31
report (6).txt:Transaktionen: 2
report (7).txt:Transaktionen: 37
report (8).txt:Transaktionen: 11
report (9).txt:Transaktionen: 29
report.txt:Transaktionen: 18
die Dateinamen werden mit ausgegeben. Ich möchte da gern einen anderen Trenner hinter dem Dateinamen haben. Statt : halt , oder gar kein Dateiname.

Benutzeravatar
framp
Moderator
Moderator
Beiträge: 4247
Registriert: 6. Jun 2004, 20:57
Wohnort: bei Stuttgart
Kontaktdaten:

Re: CSV Datei aufsplitten in mehrere Files

Beitrag von framp » 2. Apr 2017, 22:00

Wo kommen jetzt die Transaktionen her? Das passt nicht zu Deiner Eingangsfrage :Kopfkratz:

BTW: Ich habe Deinen vorherigen Post für Dich anonymisiert und foo@bar als System und Benutzer eingesetzt :-)

Flash
Member
Member
Beiträge: 210
Registriert: 24. Nov 2005, 17:54

Re: CSV Datei aufsplitten in mehrere Files

Beitrag von Flash » 2. Apr 2017, 22:08

Das ist jetzt einfach nur eine Beispielausgabe. Hmmmm...

Ich versuchs mal anders. Wenn du grep mit * aufrufst sieht die ausgabe immer so aus
<dateiname>.<endung>:<zeile die durch das suchmuster gefunden wurde>

Was ich will ist:
<dateiname>.<endung>,<zeile die durch das suchmuster gefunden wurde>

Benutzeravatar
framp
Moderator
Moderator
Beiträge: 4247
Registriert: 6. Jun 2004, 20:57
Wohnort: bei Stuttgart
Kontaktdaten:

Re: CSV Datei aufsplitten in mehrere Files

Beitrag von framp » 2. Apr 2017, 22:24

Das verstehe ich jetzt :)

Um diese Ausgabe zu erhalten muss ich noch -H als Parameter bei grep angeben. Erst der bewirkt bei mir die Ausgabe des Dateinamens von dem Match. Das entspricht zwar nicht mehr Deinen Eingangsanforderungen aber das läßt sich auch leicht lösen :fies:

Hänge einfach einen Pipe zu sed dran wo Du das erste : durch ein , ersetzt ;)

Code: Alles auswählen

| sed 's/:/,/'

Flash
Member
Member
Beiträge: 210
Registriert: 24. Nov 2005, 17:54

Re: CSV Datei aufsplitten in mehrere Files

Beitrag von Flash » 2. Apr 2017, 23:12

Das scheint nicht zu funktionieren. An der Ausgabe ändert es nichts. (Liegt das daran, dass vor dem : definitiv kein Space ist?)

Mein Script sieht aktuell so aus:

Code: Alles auswählen

for t in Leerzeichen Separierte Liste; 
do 
    echo "Creating $t.csv ...";
    echo "schreibe Header";
    echo '"Datum/Uhrzeit","Typ","Beschreibung","Gesamt"' > $t.csv;
    
    echo "schreibe zeilen aus dateien";
    grep $t * >> $t.csv | sed 's/:/,/';
    
done
Das Ergebnis sieht so aus:

Code: Alles auswählen

"Datum/Uhrzeit","Typ","Beschreibung","Gesamt"
wasAnderes.csv:"28.12.2015 13:05:53 GMT+00:00","FooBar12gg","Item Foo Bar 12 gg","3,18"

Benutzeravatar
framp
Moderator
Moderator
Beiträge: 4247
Registriert: 6. Jun 2004, 20:57
Wohnort: bei Stuttgart
Kontaktdaten:

Re: CSV Datei aufsplitten in mehrere Files

Beitrag von framp » 2. Apr 2017, 23:26

Code: Alles auswählen

grep $t * >> $t.csv | sed 's/:/,/';
ist falsch. Da schreibst Du das grep Ergebnis in die Datei ohne es vorher per sed zu ändern.

Code: Alles auswählen

grep $t * | sed 's/:/,/' >> $t.csv
wird aber funktionieren ;)

PS: Warum benutzt Du >> ? Ich würde > benutzen.

abgdf
Guru
Guru
Beiträge: 3073
Registriert: 13. Apr 2004, 21:15

Re: CSV Datei aufsplitten in mehrere Files

Beitrag von abgdf » 3. Apr 2017, 00:09

Ey Leude, ihr wißt doch, daß das was für Perl ist. ;)

Flash
Member
Member
Beiträge: 210
Registriert: 24. Nov 2005, 17:54

Re: CSV Datei aufsplitten in mehrere Files

Beitrag von Flash » 7. Apr 2017, 21:32

Ich meld mich mal zurück. Eins vorweg, Perl ist keine Option. Ich will zumindest grob verstehen was passiert. ;)

Ich benutze >> statt > weil sonst der Header verschwindet den ich vorher in die Datei geschrieben habe.

Das Script funktioniert ganz gut. Allerdings würde ich nun gern etwas gewagtes versuchen.

die CSV Zeilen sehen ungefähr so aus

Code: Alles auswählen

"asdasd_asdasda_dasdas","TYP-A","000-123213-4121231","fhjkasdasdsa asdas asdasda","12","35678","fhjkasdasdsa asdas asdasda"
"avgask_fsaasda_dasdas","TYP-A","000-123213-4121231","fhjkasdasdsa asdas asdasda","13","35678","fhjkasdasdsa asdas asdasda"
"asdasd_asdasda_dasdas","TYP-B","000-123213-4121231","fhjkasdasdsa asdas asdasda","2","35678","fhjkasdasdsa asdas asdasda"
"asdasd_asdasda_dasdas","TYP-A","000-123213-4121231","fhjkasdasdsa asdas asdasda","222","35678","fhjkasdasdsa asdas asdasda"
Ich möchte nun gern folgendes machen: Wenn in der Spalte mit TYP- ein "TYP-B" steht, dann soll die Zahl 3 Spalten weiter hinten negiert werden. Also im Fall oben aus der 2 soll eine -2 werden.
Ich hatte mir überlegt, man könnte ja einen RegEx Matcher bauen der ab TYP-B sucht und durch ein geschicktes Muster genau das erreicht. Nur ist mein RegEx doch zu schwach.

abgdf
Guru
Guru
Beiträge: 3073
Registriert: 13. Apr 2004, 21:15

Re: CSV Datei aufsplitten in mehrere Files

Beitrag von abgdf » 8. Apr 2017, 01:32

Flash hat geschrieben:
7. Apr 2017, 21:32
Ich meld mich mal zurück. Eins vorweg, Perl ist keine Option. Ich will zumindest grob verstehen was passiert. ;)
...
Ich möchte nun gern folgendes machen: Wenn in der Spalte mit TYP- ein "TYP-B" steht, dann soll die Zahl 3 Spalten weiter hinten negiert werden. Also im Fall oben aus der 2 soll eine -2 werden.
Ich hatte mir überlegt, man könnte ja einen RegEx Matcher bauen der ab TYP-B sucht und durch ein geschicktes Muster genau das erreicht. Nur ist mein RegEx doch zu schwach.
Schade, wäre alles kein Problem:

Code: Alles auswählen

#!/usr/bin/perl

use warnings;
use strict;

my $DATA = <<'END_DATA';
sdsa asdas asdasda","12","35678","fhjkasdasdsa asdas asdasda"
"avgask_fsaasda_dasdas","TYP-A","000-123213-4121231","fhjkasdasdsa asdas asdasda","13","35678","fhjkasdasdsa asdas asdasda"
"asdasd_asdasda_dasdas","TYP-B","000-123213-4121231","fhjkasdasdsa asdas asdasda","2","35678","fhjkasdasdsa asdas asdasda"
"asdasd_asdasda_dasdas","TYP-A","000-123213-4121231","fhjkasdasdsa asdas asdasda","222","35678","fhjkasdasdsa asdas asdasda"
END_DATA

my @a = split(/\n/, $DATA);
my $i;
foreach $i (@a) {
    if ($i =~ /TYP-B/) {
        my @b = split(/,/, $i);
        my $num = substr($b[4], 1);
        chop($num);
        $num = $num * -1;
        $b[4] = '"' . $num . '"';
        $i = join(",", @b);
    }
    print "$i\n";
}

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast