it-swarm.com.de

Konvertieren von CSV in TSV

Ich habe eine Reihe großer CSV-Dateien und möchte sie in TSV (tabulatorgetrenntes Format). Die Komplikation besteht darin, dass in den Feldern der CSV-Datei Kommas stehen, z.

 A,,C,"D,E,F","G",I,"K,L,M",Z

Erwartete Ausgabe:

 A      C   D,E,F   G   I   K,L,M   Z

(wo Leerzeichen dazwischen 'harte' Tabulatoren sind)

Ich habe Perl, Python und Coreutils auf diesem Server installiert.

28
DarkHeart

Python

Fügen Sie der Datei csv2tab.sh Hinzu und machen Sie sie ausführbar

#!/usr/bin/env python
import csv, sys
csv.writer(sys.stdout, dialect='Excel-tab').writerows(csv.reader(sys.stdin))

Testläufe

$ echo 'A,,C,"D,E,F","G",I,"K,L,M",Z' | ./csv2tab.sh                         
A       C   D,E,F   G   I   K,L,M   Z
$ ./csv2tab.sh < data.csv > data.tsv && head data.tsv                                                   
1A      C   D,E,F   G   I   K,L,M   Z
2A      C   D,E,F   G   I   K,L,M   Z
3A      C   D,E,F   G   I   K,L,M   Z
41
cricket_007

Verwenden Sie csvkit (Python), zum Beispiel:

$ csvformat -T in.csv > out.txt

Streamen mit korrektem CSV- und TSV-Zitat und Escape

Es ist in apt und anderen Paketmanagern

19
Neil McGuigan

Zum Spaß sed.

sed -E 's/("([^"]*)")?,/\2\t/g' file

Wenn Ihr sed-E Nicht unterstützt, versuchen Sie es mit -r. Wenn Ihr sed\t Für eine Literal-Registerkarte nicht unterstützt, versuchen Sie, eine Literal-Registerkarte einzufügen (in vielen Shells, ctrl- -vtab) oder verwenden Sie in Bash eine Zeichenfolge im C-Stil $'...' (in diesem Fall muss der Backslash in \2 verdoppelt werden). Wenn Sie die Anführungszeichen behalten möchten, verwenden Sie \1 Anstelle von \2 (In diesem Fall ist das innere Klammerpaar unbrauchbar und kann entfernt werden).

Dies macht keinen Versuch, maskierte doppelte Anführungszeichen in doppelte Anführungszeichen zu verarbeiten. Einige CSV-Dialekte unterstützen dies, indem sie das zitierte doppelte Anführungszeichen (sic) verdoppeln.

19
tripleee

Eine Option könnte Perls Text :: CSV Modul sein, z.

Perl -MText::CSV -lne 'BEGIN { $csv = Text::CSV->new() }
  print join "\t", $csv->fields() if $csv->parse($_)
' somefile

demonstrieren

echo 'A,,C,"D,E,F","G",I,"K,L,M",Z' |
  Perl -MText::CSV -lne 'BEGIN { $csv = Text::CSV->new() }
  print join "\t", $csv->fields() if $csv->parse($_)
'
A       C   D,E,F   G   I   K,L,M   Z
13
steeldriver

Perl

Perl -lne '
   my $re = qr/,(?=(?:[^"]*"[^"]*")*(?![^"]*"))/;
   print join "\t", map { s/(?<!\\)"//gr =~ s/\\"/"/gr } split $re;
'

Awk

awk -v Q=\" -v FPAT="([^,]*)|(\"[^\"]+\")" -v OFS="\t" '{
   for (i=1; i<=NF; ++i)
      if ( substr($i, 1, 1) == Q )
         $i = substr($i, 2, length($i) - 2)
   print $1, $2, $3, $4, $5, $6, $7, $8
}'

Ergebnis:

A               C       D,E,F   G       I       K,L,M   Z
7
user218374

Wenn Sie das Dienstprogramm csvtool haben oder installieren können:

csvtool -t COMMA -u TAB cat in.csv > out.ctv

Beachten Sie, dass csvtool aus irgendeinem Grund keine Manpage hat, aber csvtool --help druckt ein paar hundert Dokumentationszeilen.

5
Keith Thompson

Die thermonukleare Fliegenklatschlösung muss libreoffice verwenden. Während https://ask.libreoffice.org/en/question/19042/is-is-possible-to-convert-comma-separated-value-csv-to-tab-separated-value-tsv-via -headless-mode / schlägt vor, dass dies nicht möglich ist, aber es ist falsch (oder nur veraltet?) und der folgende Befehl funktioniert auf meinem 5.3.:

loffice "-env:UserInstallation=file:///tmp/LibO_Conversion" --convert-to csv:"Text - txt - csv (StarCalc)":9,34,UTF8 --headless --outdir some/path --infilter='csv:44,34,UTF8' *.csv

das Argument env könnte übersprungen werden, aber auf diese Weise werden die Dokumente nicht in Ihrem letzten Dokument angezeigt.

5
chx

Die Verwendung von mlr ist fast prägnant, aber das Deaktivieren von Headern erfordert lange Optionen:

mlr --c2t --implicit-csv-header --headerless-csv-output cat file.csv 

Ausgabe:

A       C   D,E,F   G   I   K,L,M   Z
4
agc

Ich habe einen Open-Source-Konverter von CSV zu TSV erstellt, der die beschriebenen Transformationen verarbeitet. Es ist ziemlich schnell und kann einen Blick wert sein, wenn ständig große CSV-Dateien konvertiert werden müssen. Das Tool ist Teil von eBay TSV Utilities Toolkit (csv2tsv Dokumentation hier ). Standardoptionen reichen für die beschriebene Eingabe aus:

$ csv2tsv file.csv > file.tsv

Eine Überlegung bei der Konvertierung von CSV in TSV ist die Behandlung von Feld- und Datensatztrennzeichen (Komma und Zeilenumbruch) in den Daten. CSV verwendet eine Escape-Syntax. Wenn das Ziel darin besteht, die Ausgabe mit Unix-Tools wie cut, awk usw. zu verwenden, muss die Ausgabe frei von Escapezeichen sein. Die meisten hier aufgeführten Lösungen erzeugen Escapezeichen im CSV-Stil, wenn Trennzeichen in den Daten enthalten sind. csv2tsv unterscheidet sich von anderen Lösungen dadurch, dass es TSV ohne Flucht erzeugt. Einzelheiten finden Sie in der Dokumentation.

Um zu sehen, was eine bestimmte Lösung bewirkt, konvertieren Sie eine CSV mit Kommas, Tabulatoren, Anführungszeichen und Zeilenumbrüchen in den Daten. Zum Beispiel:

$ echo $'Line,Field1,Field2\n1,"Comma: |,|","Quote: |""|"\n"2","TAB: |\t|","Newline: |\n|"' | <conversion-script-or-command>

Lösungen, die Escapezeichen generieren, setzen doppelte Anführungszeichen um die Felder, die Anführungszeichen, Zeilenumbrüche oder Tabulatoren enthalten.

4
JonDeg

Vim

Nur zum Spaß können Regex-Substitutionen in Vim durchgeführt werden. Hier ist eine mögliche vierzeilige Lösung, angepasst von: https://stackoverflow.com/questions/33332871/remove-all-commas-between-quotes-with-a-vim-regex

  1. Kommas zwischen Anführungszeichen werden zuerst in Unterstriche (oder andere fehlende Zeichen) geändert.
  2. Alle anderen Kommas werden durch Tabulatoren ersetzt.
  3. Unterstriche in Anführungszeichen werden in Kommas wiederhergestellt.
  4. Anführungszeichen werden entfernt.

    :%s/".\{-}"/\=substitute(submatch(0), ',', '_' , 'g')/g
    :%s/,/\t/g
    :%s/_/,/g
    :%s/"//g
    

Um die Lösung etwas zu skripten, können die vier obigen Zeilen (ohne führenden Doppelpunkt) in einer Datei gespeichert werden, z. to_tsv.vim. Öffnen Sie jede CSV zur Bearbeitung mit Vim und source the to_tsv.vim Skript in der Vim Befehlszeile (angepasst von https://stackoverflow.com/questions/3374179/run-vim-script) -from-vim-commandline/8806874 # 8806874 ):

    :source /path/to/vim/filename/to_tsv.vim
2
jubilatious1

Bei Perl wird davon ausgegangen, dass die CSV-Felder kein eingebettetes " oder Zeilenumbrüche oder Tabulatoren:

Perl -pe 's{"(.*?)"|,}{$1//"\t"}ge'
1

Hier ist das Beispiel für die Konvertierung von CSV in TSV mit dem Dienstprogramm jq :

$ jq -rn '@tsv "\(["A","","C","D,E,F","G","I","K,L,M","Z"])"'
A       C   D,E,F   G   I   K,L,M   Z

oder:

$ echo '["A","","C","D,E,F","G","I","K,L,M","Z"]' | jq -r @tsv
A       C   D,E,F   G   I   K,L,M   Z

Das CSV-Format muss jedoch gut formatiert sein, sodass jede Zeichenfolge in Anführungszeichen gesetzt werden muss.

Quelle: Einfaches TSV-Ausgabeformat .

1
kenorb

Das Folgende ist einfach eine Korrektur von die Antwort von @ Tripleee , so dass alle Anführungszeichen aus dem letzten Feld entfernt werden, so wie es ist tut mit allen anderen Feldern.

Um zu zeigen, was korrigiert wird, finden Sie unten die Antwort eines Tripleee sowie eine geringfügige Änderung der Beispieldaten des OP mit zusätzlichen Anführungszeichen um das Finale ' [~ # ~] z [~ # ~] 'Feld.

echo 'A,,C,"D,E,F","G",I,"K,L,M","Z"' |  sed -r -e 's/("([^"]*)")?,/\2\t/g'
A       C   D,E,F   G   I   K,L,M   "Z"

Sie können sehen, dass ' [~ # ~] z [~ # ~] ' mit Anführungszeichen versehen ist. Dies unterscheidet sich von der Behandlung der inneren Felder. Zum Beispiel enthält das ' [~ # ~] g [~ # ~] ' keine Anführungszeichen.

Der folgende Befehl verwendet eine zweite Ersetzung, um die letzte Spalte zu bereinigen:

echo 'A,,C,"D,E,F","G",I,"K,L,M","Z"' |  sed -r -e 's/("([^"]*)")?,/\2\t/g' \
                                                -e 's/\t"([^"]*)"$/\t\1/'
A       C   D,E,F   G   I   K,L,M   Z
0
Fonnae