web-dev-qa-db-fra.com

moyen le plus rapide de convertir un fichier délimité par des tabulations en csv sous linux

J'ai un fichier délimité par des tabulations qui a plus de 200 millions de lignes. Quel est le moyen le plus rapide de linux pour convertir cela en un fichier csv? Ce fichier contient plusieurs lignes d'informations d'en-tête que je devrai supprimer, mais le nombre de lignes d'en-tête est connu. J'ai vu des suggestions pour sed et gawk, mais je me demande s'il existe un choix "préféré".

Juste pour clarifier, il n'y a pas d'onglets incorporés dans ce fichier.

41
andrewj

Si tout ce que vous devez faire est translate tous les caractères de tabulation en caractères de virgule, tr est probablement le chemin à parcourir.

L'espace vide ici est un onglet littéral:

$ echo "hello   world" | tr "\\t" ","
hello,world

Bien entendu, si vous avez incorporé des onglets dans des littéraux de chaîne dans le fichier, ceux-ci seront également traduits incorrectement. mais des onglets littéraux intégrés seraient assez rares.

42
Mark Rushakoff

Si vous craignez les virgules intégrées, vous devrez utiliser une méthode légèrement plus intelligente. Voici un script Python qui extrait les lignes TSV de stdin et écrit les lignes CSV sur stdout:

import sys
import csv

tabin = csv.reader(sys.stdin, dialect=csv.Excel_tab)
commaout = csv.writer(sys.stdout, dialect=csv.Excel)
for row in tabin:
  commaout.writerow(row)

Exécutez-le à partir d'un shell comme suit:

python script.py < input.tsv > output.csv
71
Perl -lpe 's/"/""/g; s/^|$/"/g; s/\t/","/g' < input.tab > output.csv

Perl est généralement plus rapide dans ce genre de choses que sed, awk et Python.

19
pabs
sed -e 's/"/\\"/g' -e 's/<tab>/","/g' -e 's/^/"/' -e 's/$/"/' infile > outfile

Putain de critiques, tout cite, CSV s'en fiche. 

<tab> est le caractère de tabulation réel.\t n'a pas fonctionné pour moi. En bash, utilisez ^ V pour le saisir.

6
Will Hartung
  • Si vous souhaitez convertir l'intégralité du fichier tsv en un fichier csv:

    $ cat data.tsv | tr "\\t" "," > data.csv
    

  • Si vous souhaitez omettre certains champs:

    $ cat data.tsv | cut -f1,2,3 | tr "\\t" "," > data.csv
    

    La commande ci-dessus convertira le fichier data.tsv en fichier data.csvcontenant uniquement les trois premiers champs.

5
Gopal Jha

La solution python de @ ignacio-vazquez-abrams est excellente! Pour les personnes qui cherchent à analyser les onglets des délimiteurs, la bibliothèque vous permet en fait de définir des délimiteurs arbitraires. Voici ma version modifiée pour gérer les fichiers délimités par des tubes:

import sys
import csv

pipein = csv.reader(sys.stdin, delimiter='|')
commaout = csv.writer(sys.stdout, dialect=csv.Excel)
for row in pipein:
  commaout.writerow(row)
5
jtlai

en supposant que vous ne voulez pas changer l'en-tête et en supposant que vous n'avez pas d'onglets incorporés

# cat file
header  header  header
one     two     three

$ awk 'NR>1{$1=$1}1' OFS="," file
header  header  header
one,two,three

NR> 1 saute le premier en-tête. vous avez mentionné que vous connaissez le nombre de lignes d'en-tête, utilisez donc le nombre correct pour votre propre cas. avec cela, vous n'avez également pas besoin d'appeler d'autres commandes externes. une seule commande awk fait le travail. 

une autre façon si vous avez des colonnes vierges et que vous vous souciez de cela.

awk 'NR>1{gsub("\t",",")}1' file

en utilisant sed

sed '2,$y/\t/,/' file #skip 1 line header and translate (same as tr)
3
ghostdog74

Vous pouvez également utiliser xsv pour cela

xsv input -d '\t' input.tsv > output.csv

Lors de mon test sur un fichier tsv de 300 Mo, il était environ 5 fois plus rapide que la solution python (2,5 vs 14).

1
mloughran

l'awel oneliner suivant prend en charge les guillemets + quote-escaping

printf "flop\tflap\"" | awk -F '\t' '{ gsub(/"/,"\"\"\"",$i); for(i = 1; i <= NF; i++) { printf "\"%s\"",$i; if( i < NF ) printf "," }; printf "\n" }'

donne

"flop","flap""""
0
coderofsalvation

Je pense qu'il est préférable de ne pas chatter le fichier car cela peut créer un problème dans le cas d'un fichier volumineux. La meilleure façon peut être

$ tr ',' '\t' < csvfile.csv > tabdelimitedFile.txt

La commande obtiendra une entrée de csvfile.csv et stockera le résultat sous forme de tabulation séparée dans tabdelimitedFile.txt.

0
Mian Asbat Ahmad