2010-03-29 20 views
36

Tengo un archivo delimitado por tabulaciones que tiene más de 200 millones de líneas. ¿Cuál es la forma más rápida en Linux para convertir esto a un archivo csv? Este archivo tiene varias líneas de información de encabezado que tendré que quitar en el futuro, pero se conoce el número de líneas de encabezado. He visto sugerencias para sed y gawk, pero me pregunto si hay una opción "preferida".forma más rápida de convertir archivo delimitado por tabulaciones a csv en linux

Solo para aclarar, no hay pestañas incrustadas en este archivo.

+0

Para csv a cuestiones delimitador tsv y embebidos, ver también responde a http://stackoverflow.com/questions/13475535/replace-every-comma-not-enclosed-in-a-pair-of-double -quotes-with (también relevante: http://unix.stackexchange.com/questions/48672/remove-comma-between-the-quotes-only-in-a-comma-delimited-file). –

Respuesta

38

Si todo lo que necesita hacer es traduzca todos los caracteres de tabulación a los caracteres de coma, tr es probablemente el camino a seguir.

El espacio en blanco aquí es una pestaña literal:

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

Por supuesto, si usted ha incrustado pestañas dentro de los literales de cadena en el archivo, esto se traducirá incorrectamente esos también; pero las pestañas literales incrustadas serían bastante poco comunes.

+13

Más comunes son las comas incrustadas en el origen, que luego requieren envolver con comillas. Lo cual es problemático si hay citas incrustadas ... – kibibu

+0

Gracias por la sugerencia 'tr'. ¿Cómo se compara con 'sed' con la velocidad? Supongamos que quiere omitir el encabezado de inicio en el número de línea x y continuar con el resto del archivo. ¿Hay alguna manera de implementar esto con 'tr'? (También debo aclarar que no hay comas incrustadas en el archivo.) – andrewj

+0

@andrewj: 'tr' debe ser mucho más rápido, ya que solo está haciendo el reemplazo carácter por carácter en lugar de la coincidencia de expresiones regulares. En cuanto a omitir encabezado, lo más fácil es procesar en dos partes: si conoce la longitud, 'head -n input> output; cola -n + entrada | tr ... >> salida'; si no conoce la longitud, probablemente algo con 'grep -n' ... – Cascabel

62

Si le preocupan las comas incrustadas, entonces deberá usar un método un poco más inteligente. Aquí hay un script en Python que recibe líneas TSV de la entrada estándar y escribe las líneas CSV a la salida estándar:

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) 

ejecutarlo desde una cáscara de la siguiente manera:

python script.py <input.tsv> output.csv 
+1

A menos que sepa con seguridad que no hay comillas incrustadas ni pestañas incrustadas, esta es una forma muy confiable de hacerlo. Aunque probablemente no cumpla con los criterios para ser "el más rápido". – leedm777

+2

Puede que no sea "el más rápido", pero sí maneja las pestañas y comillas integradas. – anshuman

+1

Esto rocas. Estaba escribiendo un criptográfico script sed para encargarme de esto en bash, pero eso no puede competir con la completitud de la biblioteca csv de python. Gracias Ignacio, por esta oferta. En cuanto a la velocidad, la facilidad de uso y la confiabilidad de la velocidad de la autopista, esto es bastante rápido. :-) – dlink

3

asumiendo que no desea cambiar la cabecera y asumiendo no tiene pestañas incrustadas

# cat file 
header header header 
one  two  three 

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

NR> 1 omite el primer encabezado. Usted mencionó que sabe cuántas líneas de encabezado, así que use el número correcto para su propio caso. con esto, tampoco necesitas llamar a ningún otro comando externo. solo un comando awk hace el trabajo.

de otra manera si tiene columnas en blanco y eso le importa.

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

usando sed

sed '2,$y/\t/,/' file #skip 1 line header and translate (same as tr) 
6
sed -e 's/"/\\"/g' -e 's/<tab>/","/g' -e 's/^/"/' -e 's/$/"/' infile > outfile 

diablo con los críticos, cita todo, CSV no le importa.

<tab> es el carácter de tabulación real. no funcionó para mí. En bash, use^V para ingresarlo.

+0

pestaña, puede hacer 'sed-e 's /"/\\ "/ g' -e" s/\ t/\ ", \"/g "-e 's/^ /" /' -e 's/$/"/ 'infile> archivo_explo'. –

15
perl -lpe 's/"/""/g; s/^|$/"/g; s/\t/","/g' <input.tab> output.csv 

Perl es generalmente más rápido en este tipo de cosas que sed, awk y Python.

+1

mejor respuesta para mí, solo un cambio leve, scape comillas dobles: perl -lpe 's /"/\\ "/ g; s/^ | $ /"/g; s/\ t/","/g '<... – Lix

+0

larga vida Perl! Exactamente el one-liner que necesitaba. – Debriter

+0

Eres un salvador – Yankee

0

la siguiente oneliner awk apoya citando + Cotización en escapar

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

da

"flop","flap"""" 
4

@ solución pitón Ignacio Vázquez-Abrams 's es grande! Para las personas que buscan analizar delimitadores de otra pestaña, la biblioteca en realidad le permite establecer delimitadores arbitrarios.Aquí está mi versión modificada para manejar archivos de tubo delimitado por:

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) 
4
  • Si desea convertir todo el archivo TSV en un archivo csv:

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

  • Si quieren para omitir algunos campos:

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

    The El comando anterior convertirá el archivo data.tsv en el archivo data.csv que contiene solo los primeros tres campos.

+1

muy bueno :) –

Cuestiones relacionadas