Самый быстрый способ конвертировать файл с разделителями табуляции в CSV в Linux - PullRequest
46 голосов
/ 29 марта 2010

У меня есть файл с разделителями табуляции, который содержит более 200 миллионов строк. Какой самый быстрый способ в Linux для преобразования этого в CSV-файл? Этот файл содержит несколько строк информации заголовка, которые мне нужно будет удалить в будущем, но количество строк заголовка известно. Я видел предложения для sed и gawk, но мне интересно, есть ли «предпочтительный» выбор.

Просто чтобы уточнить, в этом файле нет встроенных вкладок.

Ответы [ 10 ]

73 голосов
/ 29 марта 2010

Если вы беспокоитесь о встроенных запятых, вам нужно использовать немного более интеллектуальный метод. Вот скрипт Python, который берет строки TSV из стандартного ввода и записывает строки CSV в стандартный вывод:

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)

Запустите его из оболочки следующим образом:

python script.py < input.tsv > output.csv
48 голосов
/ 29 марта 2010

Если все, что вам нужно сделать, это перевести все символы табуляции в символы запятых, tr, вероятно, путь.

Пробел здесь - буквенная вкладка:

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

Конечно, если у вас есть встроенные вкладки внутри строковых литералов в файле, это также неправильно переведет их; но встроенные буквенные вкладки были бы довольно необычными.

19 голосов
/ 30 марта 2010
perl -lpe 's/"/""/g; s/^|$/"/g; s/\t/","/g' < input.tab > output.csv

Perl обычно быстрее в таких вещах, чем sed, awk и Python.

7 голосов
/ 31 января 2017
  • Если вы хотите преобразовать весь файл TSV в файл CSV:

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

  • Если вы хотите пропустить некоторые поля:

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

    Приведенная выше команда преобразует файл data.tsv в файл data.csv , содержащий только первые три поля .

6 голосов
/ 29 марта 2010
sed -e 's/"/\\"/g' -e 's/<tab>/","/g' -e 's/^/"/' -e 's/$/"/' infile > outfile

Будь прокляты критики, цитируй все, CSV не волнует.

<tab> - фактический символ табуляции. у меня не получилось. В bash используйте ^ V для ввода.

5 голосов
/ 22 января 2015

@ python-решение ignacio-vazquez-abrams великолепно! Для людей, которые хотят разобрать другие вкладки, библиотека фактически позволяет вам установить произвольный разделитель. Вот моя модифицированная версия для обработки файлов с разделителями трубы:

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)
3 голосов
/ 29 марта 2010

при условии, что вы не хотите менять заголовок, и при условии, что у вас нет встроенных вкладок

# cat file
header  header  header
one     two     three

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

NR> 1 пропускает первый заголовок. Вы упомянули, что знаете, сколько строк заголовка, поэтому используйте правильный номер для своего случая. при этом вам также не нужно вызывать какие-либо другие внешние команды. только одна команда awk делает эту работу.

иначе, если у вас есть пустые столбцы, и вы заботитесь об этом.

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

с использованием sed

sed '2,$y/\t/,/' file #skip 1 line header and translate (same as tr)
1 голос
/ 09 мая 2019

Вы также можете использовать xsv для этого

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

В моем тесте для файла TSV объемом 300 МБ он был примерно в 5 раз быстрее, чем решение Python (2,5 с против 14 с).

0 голосов
/ 28 апреля 2018

Я думаю, что лучше не катать файл, потому что это может создать проблему в случае большого файла. Лучший способ может быть

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

Команда получит входные данные из csvfile.csv и сохранит результат в виде табуляции, разделенной в tabdelimitedFile.txt

0 голосов
/ 27 августа 2014

следующий awk oneliner поддерживает цитирование + экранирование кавычек

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

дает

"flop","flap""""
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...