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

Benutzeravatar
robi
Moderator
Moderator
Beiträge: 3160
Registriert: 25. Aug 2004, 02:13

Re: CSV Datei aufsplitten in mehrere Files

Beitrag von robi » 9. Apr 2017, 01:59

Flash hat geschrieben:
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 (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.
Dann wie folgt zu lösen
framp hat geschrieben:
2. Apr 2017, 22:24
Hänge einfach einen Pipe zu sed dran wo Du das erste : durch ein , ersetzt ;)

Code: Alles auswählen

| sed 's/:/,/'

ist der falsche Weg, Immer so einfach wie nur möglich, und nicht im ersten Schritt gleich irgendwelche aufkommenden Probleme gleich mit zusätzlichen Code beseitigen, sonder immer zuerst mal in die Manpage schauen ob es da nicht vielleicht Optionen gibt die einem nicht so geläufig sind, aber die Probleme schon vorn vorne herein beseitigen.
grep -h unterdrückt die Ausgabe von Dateinamen. -H ( wie framp schon oben bemerkt) gibt sie expilizied mit aus, auch dann wenn nur eine einzige Datei durchsucht wird.
Flash hat geschrieben:
7. Apr 2017, 21:32
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.
Mal abgesehen, was du 3 Spalten weiter als Zahl bezeichnest steht in Hochkommas eingeschlossen und ist folglich Text, aber wir wollen mal nicht kleinlich sein.

sicherlich kann man da einen RegEx bauen, der das erledigt, zB.

Code: Alles auswählen

sed  's/\(TYP-B\",[^,]\+,[^,]\+,\"\)/\1-/'
bringt dich aber nicht weiter wenn du ihn nicht wirklich verstehst, wie er funktioniert.
Möglichkeit B wäre in der Bash die Zeile in Spalten zu zerlegen, dann könntest du bequem die Spalte 2 nach "TYP-A/B" absuchen und dann die Spalte 5 bequem ändern. und entsprechend dem Ergebnis von Test auf Spalte 2 das Ganze dann in die jeweilige Datei schreiben. Kein Problem sowas in Bash zu schreiben, aber kann dir nicht versprechen das dann noch jeder annähernd verstehst, was dort passiert.

Code: Alles auswählen

#!/bin/bash
FILEA="FILE_TYP_A.txt"
FILEB="FILE_TYP_B.txt"
echo "Begrüßungstext für Type-A" > $FILEA
echo "Begrüßungstext für Type-B" > $FILEB

OLD_IFS=$IFS
IFS=","
while read A B C D E F G 
do 
      if [ "${B}" == \""TYP-B\"" ] 
      then   
         E=${E/\"/\"-}
         echo $A,$B,$C,$D,$E,$F,$G >> $FILEB
      else 
         if [ -n "$B" ] 
         then  
            echo $A,$B,$C,$D,$E,$F,$G >> $FILEA 
         fi
      fi
 done < <(cat $*) 
IFS=$OLD_IFS
Ausführungsrechte auf Script geben, Aufruf : ./script Datei1.csv Datei2.csv .............

Wobei wir wieder bei meinem Satz von oben sind, Immer so einfach wie nur möglich, also wenn möglich ein Programm/Tool verwenden das für die Aufgabe geeignet ist
und möglichst intern schon genau so arbeitet wie man es braucht, das spart nen Haufen Zeit bei der Scripterstellung und beim Testen.
awk bietet sich hier natürlich an

Code: Alles auswählen

#!/usr/bin/awk -f
 
 BEGIN {
       FS=","
       OFS=","
       FILE1="TYP_A.txt"
       FILE2="TYP_B.txt"
       print "HALLO Begrüßungstest für TYP_A" > FILE1 
       print "HALLO Begrüßungstest für TYP_B" > FILE2 
 }
 $2 ~ /TYP-A/ {
       print ( $0 ) >> FILE1 
 }
 $2 ~ /TYP-B/ {
       sub("\"","\"-",$5)                                    # im 5. Feld wird  das erste " durch "-  ausgewechselt
       print( $0 ) >>  FILE2
 }
Ausführungsrechte auf Script geben, Aufruf : ./script Datei*.csv

Ist auch nicht schwieriger zu verstehen und die gesamte Dokumentation für awk umfasst nur die Halbe Größe der Manpages von bash und bashutils die man eventuell durchsuchen müßte um das bashscript zu verstehen.

robi

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

Re: CSV Datei aufsplitten in mehrere Files

Beitrag von abgdf » 9. Apr 2017, 02:14

robi hat geschrieben:
9. Apr 2017, 01:59
sicherlich kann man da einen RegEx bauen, der das erledigt, zB.

Code: Alles auswählen

sed -n 's/\(TYP-B\",[^,]\+,[^,]\+,\"\)/\1-/p'
bringt dich aber nicht weiter wenn du ihn nicht wirklich verstehst, wie er funktioniert.
Da krieg' ich die Zahnstocherkrankheit (sed ////\\\\\\ - Zahnstocher). :mrgreen:
robi hat geschrieben:
9. Apr 2017, 01:59
awk bietet sich hier natürlich an
...
Ist auch nicht schwieriger zu verstehen und die gesamte Dokumentation für awk umfasst nur die Halbe Größe der Manpages von bash und bashutils die man eventuell durchsuchen müßte um das bashscript zu verstehen.
Ja, ja. Seit zig Jahren laufen diese Themen immer in der gleichen Weise, und noch nie hat jemand deswegen awk gelernt. (Ok, Perl wohl auch nicht).
Aber man kann wirklich nicht sagen, daß awk leicht zu verstehen sei. Es geht eine Datei eben zeilenweise durch (wie "perl -p -i ..."). In der Perl-Doku ("perldoc perlrun") steht zu dem Mechanismus:
causes Perl to assume the following loop around your program, which makes it iterate over filename arguments somewhat like ...
und das ist eben überhaupt nicht leicht zu verstehen, da verliert man ganz leicht die Kontrolle. Da ist es mir schon wesentlich lieber, wenn man gleich etwas Richtiges lernt, und den "Loop around your program" selbst schreibt, bzw. überhaupt schreiben kann (awk läßt das ja gar nicht zu). Also, ich vermeide diese vermeintlich kurzen Einzeiler a la "perl -p -i" oder eben "awk ...", wenn ich kann. Da schreib' ich mir lieber mein Skript ganz selbst.
In Perl ist das auch viel leichter als in bash. Und zwar, weil Dateinamen da so funktionieren, wie man es erwartet: Leerzeichen, Sonderzeichen und Umlaute stellen keine Gefahr dar. Und Variablen verschwinden auch nicht plötzlich unbemerkt in Subshells.

Aber bitte, jeder wie er mag. Ich denke nur, wenn der Threadersteller nicht noch eine ganze Menge lernt (was auch immer, am besten das Richtige), wird er die Ziele, die er mit seiner Datenverarbeitung hat, nicht erreichen können.

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

Re: CSV Datei aufsplitten in mehrere Files

Beitrag von framp » 10. Apr 2017, 23:32

robi hat geschrieben:
9. Apr 2017, 01:59
framp hat geschrieben:
2. Apr 2017, 22:24
Hänge einfach einen Pipe zu sed dran wo Du das erste : durch ein , ersetzt ;)

Code: Alles auswählen

| sed 's/:/,/'

ist der falsche Weg,
Dem stimme ich so ganz zu :) Das Ziel in den Augen ist das bei Kenntnis des TEs der schnellste Weg. Aber es gibt ja bekanntlich diverse Wege nach Rom :D

Antworten