Есть ли надежный инструмент командной строки для обработки CSV-файлов?

47

Я работаю с CSV-файлами, и иногда мне нужно быстро проверить содержимое строки или столбца из командной строки. Во многих случаях cut, head, tailи друзья будут делать эту работу; тем не менее, сокращение не может легко справиться с такими ситуациями, как

"this, is the first entry", this is the second, 34.5

Здесь первая запятая является частью первого поля, но cut -d, -f1не согласна. Прежде чем сам написать решение, мне было интересно, знает ли кто-нибудь о хорошем инструменте, который уже существует для этой работы. Он должен был бы, по крайней мере, иметь возможность обрабатывать приведенный выше пример и возвращать столбец из файла в формате CSV. Другие желательные функции включают возможность выбора столбцов на основе имен столбцов, указанных в первой строке, поддержку других стилей цитирования и поддержку файлов, разделенных табуляцией.

Если вы не знаете о таком инструменте, но у вас есть предложения по реализации такой программы на Bash, Perl или Python или других распространенных языках сценариев, я не возражаю против таких предложений.

Стивен Д
источник

Ответы:

38

Вы можете использовать csvмодуль Python .

Простой пример:

import csv
reader = csv.reader(open("test.csv", "r"))
for row in reader:
    for col in row:
        print col
кендырь
источник
Мое окончательное решение было в Python, так как мой Perl был слишком ржавым. Благодарю.
Стивен Д.
2
Еще лучше, используйте Панды . Он явно предназначен для работы с табличными данными.
Джош
38

Возможно, я немного опоздал, но есть еще один инструмент, о котором стоит упомянуть: csvkit

http://csvkit.readthedocs.org/

У этого есть много инструментов командной строки, которые могут:

  • переформатирование файлов CSV,
  • конвертировать в и из CSV из различных форматов (JSON, SQL, XLS),
  • эквивалент cut, grep, sortи другие, но CSV-известно,
  • объединить разные файлы CSV,
  • делать общие запросы SQL на данные из файлов CSV.
romaia
источник
6
Отличный инструмент, который прекрасно отвечает критериям вопроса (в частности, он не требует перехода на язык программирования и хорошо приспособлен для работы с другими утилитами Unix).
mm2001
15

Похоже, работа для Perl с Text::CSV.

perl -MText::CSV -pe '
    BEGIN {$csv = Text::CSV->new();}
    $csv->parse($_) or die;
    @fields = $csv->fields();
    print @fields[1,3];
'

Смотрите документацию о том, как обрабатывать имена столбцов. Разделитель и стиль цитирования могут быть настроены с параметрами new. Смотрите также Text::CSV::Separatorдля угадывания разделителя.

Жиль "ТАК - перестань быть злым"
источник
Есть ли один вкладыш, в который вы можете это сжать. Мне нравится Perl, но только тогда, когда я могу вызвать его непосредственно из командной строки, а не с помощью скрипта
Шридхар Сарнобат
2
@ user7000, если только ваша оболочка не является (t)cshэтой командой, она будет прекрасно работать в командной строке вашей оболочки. Вы всегда можете соединить эти строки вместе, если хотите, чтобы это было в одной строке. символ новой строки обычно такой же, как пробел в синтаксисе perl, как в C.
Стефан
Я полагаю. Хотя сжатие более 2 строк в 1 - это не то, что я имею в виду под одним вкладышем. Я надеялся, что есть какой-то синтаксический сахар, который будет делать некоторые из них неявно (например, как -eсоздает неявный цикл).
Шридхар Сарнобат
10

Я нашел csvfix, инструмент командной строки делает свою работу хорошо. Вы должны будете сделать это самостоятельно однако:

http://neilb.bitbucket.org/csvfix

Он выполняет все то, что вы ожидаете, упорядочивает / выбирает столбцы, разделяет / объединяет и многое другое, что вам не хотелось бы генерировать вставки SQL из данных CSV и анализ данных CSV.

Даниэль Берк
источник
8

Если вы хотите использовать командную строку (и не создаете целую программу для выполнения работы), вы хотели бы использовать строки , проект, над которым я работаю: это интерфейс командной строки для табличных данных, но также библиотека Python для использования в ваших программах. С помощью интерфейса командной строки вы можете печатать любые данные в CSV, XLS, XLSX, HTML или любом другом табличном формате, поддерживаемом библиотекой, с помощью простой команды:

rows print myfile.csv

Если myfile.csvэто так:

state,city,inhabitants,area
RJ,Angra dos Reis,169511,825.09
RJ,Aperibé,10213,94.64
RJ,Araruama,112008,638.02
RJ,Areal,11423,110.92
RJ,Armação dos Búzios,27560,70.28

Затем строки будут печатать содержимое красивым способом, например так:

+-------+-------------------------------+-------------+---------+
| state |              city             | inhabitants |   area  |
+-------+-------------------------------+-------------+---------+
|    RJ |                Angra dos Reis |      169511 |  825.09 |
|    RJ |                       Aperibé |       10213 |   94.64 |
|    RJ |                      Araruama |      112008 |  638.02 |
|    RJ |                         Areal |       11423 |  110.92 |
|    RJ |            Armação dos Búzios |       27560 |   70.28 |
+-------+-------------------------------+-------------+---------+

Установка

Если вы являетесь разработчиком Python и уже pipустановили на свой компьютер, просто запустите внутри virtualenv или с помощью sudo:

pip install rows

Если вы используете Debian:

sudo apt-get install rows

Другие интересные функции

Преобразование форматов

Вы можете конвертировать между любыми поддерживаемыми форматами:

rows convert myfile.xlsx myfile.csv

Запросы

Да, вы можете использовать SQL в файл CSV:

$ rows query 'SELECT city, area FROM table1 WHERE inhabitants > 100000' myfile.csv
+----------------+--------+
|      city      |  area  |
+----------------+--------+
| Angra dos Reis | 825.09 |
|       Araruama | 638.02 |
+----------------+--------+

Преобразование вывода запроса в файл вместо stdout также возможно с помощью --outputпараметра.

Как библиотека Python

Вы также можете использовать свои программы на Python:

import rows
table = rows.import_from_csv('myfile.csv')
rows.export_to_txt(table, 'myfile.txt')
# `myfile.txt` will have same content as `rows print` output

Надеюсь, тебе понравится!

Альваро Жустен
источник
6

R не мой любимый язык программирования, но он хорош для таких вещей. Если ваш CSV-файл

***********
foo.csv
***********
 col1, col2, col3
"this, is the first entry", this is the second, 34.5
'some more', "messed up", stuff

Внутри интерпретатора типа R

> x=read.csv("foo.csv", header=FALSE)

> x
                     col1                col2   col3
1 this, is the first entry  this is the second   34.5
2              'some more'           messed up  stuff
> x[1]  # first col
                      col1
1 this, is the first entry
2              'some more'
> x[1,] # first row
                      col1                col2  col3
1 this, is the first entry  this is the second  34.5

Что касается других ваших запросов, для «возможности выбора столбцов на основе имен столбцов, указанных в первой строке» см.

> x["col1"]
                      col1
1 this, is the first entry
2              'some more'

Для «поддержки других стилей цитирования» см. quoteАргумент read.csv (и связанных функций). Для "поддержки файлов, разделенных табуляцией" смотрите sepаргумент read.csv (установлен sepв '\ t').

Для получения дополнительной информации см. Онлайн-справку.

> help(read.csv)
Фахим Митха
источник
Я очень знаком с R, но моей целью было получить что-то, что я мог бы легко использовать из Bash.
Стивен Д
1
@ Steven: R можно легко запустить из командной строки, точно так же, как Python или Perl, если это ваша единственная задача. Смотрите Rscript(часть базового дистрибутива R) или пакет дополнений littler. Вы можете сделать #!/usr/bin/env Rscriptили подобное.
Фахим Митха
О да. Я довольно опытный в R, но не использовал это много, чтобы создать этот тип утилиты. У меня есть кое-что работающее в Python, но я могу попытаться создать что-то и в R.
Стивен Д
4

Miller - еще один хороший инструмент для манипулирования данными на основе имен, включая CSV (с заголовками). Чтобы извлечь первый столбец файла CSV, не обращая внимания на его имя, вы должны сделать что-то вроде

printf '"first,column",second,third\n1,2,3\n' |
  mlr --csv --implicit-csv-header --headerless-csv-output cut -f 1
Стивен Китт
источник
Миллер очень впечатляет. Я бы сравнил это с awkвысокой степенью осведомленности о DSV.
Дерек Махар
3

Или, вы можете попробовать магию awk . Однако я не очень хороший пользователь awk и не могу подтвердить, что это будет работать должным образом, и как это сделать.

RVS
источник
9
Вот один awk CSV Parser, который я использовал некоторое время назад ... Кажется, он довольно хорошо продуман ... lorance.freeshell.org/csv
Peter.O
2

Чтобы использовать python из командной строки, вы можете проверить pythonpy ( https://github.com/Russell91/pythonpy ):

$ echo $'a,b,c\nd,e,f' | py '[x[1] for x in csv.reader(sys.stdin)']
b
e
RussellStewart
источник
2

попробуйте "csvtool" этот пакет, это удобный инструмент командной строки для обработки файлов CSV

Dominic
источник
1
Уже упоминалось, с более подробной информацией ...
Jasonwryan
2

cissy также выполняет обработку csv из командной строки. Он написан на C (маленький / легкий) с пакетами rpm и deb, доступными для большинства дистрибутивов.

Используя пример:

echo '"this, is the first entry", this is the second, 34.5' | cissy -c 1
"this, is the first entry"

или же

echo '"this, is the first entry", this is the second, 34.5' | cissy -c 2
 this is the second

или же

echo '"this, is the first entry", this is the second, 34.5' | cissy -c 2-
 this is the second, 34.5
slass100
источник
1

Существует также библиотека Curry для чтения / записи файлов в формате CSV: CSV .

imz - Иван Захарящев
источник
2
Не могли бы вы опубликовать пример кода, например, ответы на Perl, Python и R? (Тем более, что Curry не является распространенным языком сценариев Unix.)
Жиль "ТАК, перестань быть злым"
@ Жиль: Да, вы правы, я должен опубликовать пример кода, чтобы улучшить ответ. Я собираюсь сделать это через некоторое время.
imz - Иван Захарящев
1

У инструментов структурированного текста Github Repo есть полезный список соответствующих инструментов командной строки Linux. В частности, в разделе « Разделенные значения разделителя » перечислены несколько инструментов с поддержкой CSV, которые непосредственно поддерживают запрошенные операции.

JonDeg
источник
1

Одним из лучших инструментов является Миллер ( http://johnkerl.org/miller/doc/index.html ). Это как awk, sed, cut, join и sort для индексированных по имени данных, таких как CSV, TSV и табличный JSON.

В примере

echo '"this, is the first entry", this is the second, 34.5' | \
mlr --icsv --implicit-csv-header cat

дает тебе

1=this, is the first entry,2= this is the second,3= 34.5

Если вы хотите TSV

echo '"this, is the first entry", this is the second, 34.5' | \
mlr --c2t --implicit-csv-header cat

дает (можно удалить заголовок)

1       2       3
this, is the first entry         this is the second      34.5

Если вы хотите первый и третий столбец, измените их порядок

echo '"this, is the first entry", this is the second, 34.5' | \
mlr --csv --implicit-csv-header --headerless-csv-output cut -o -f 3,1

дает тебе

 34.5,"this, is the first entry"
aborruso
источник
1

Если вам нужен визуальный / интерактивный инструмент в терминале, я искренне рекомендую VisiData.

введите описание изображения здесь

Он имеет таблицы частот (показанные выше), сводки, плавления, диаграммы рассеяния, фильтрацию / вычисления с использованием Python и многое другое.

Вы можете передавать файлы CSV, как так

vd hello.csv

Есть варианты CSV конкретные: --csv-dialect, --csv-delimiter, --csv-quotechar, и --csv-skipinitialspaceдля тонкой настройки обработки из CSV - файлов.

DameDebugger
источник
0

Awk решение

awk -vq='"' '
func csv2del(n) {
  for(i=n; i<=c; i++)
    {if(i%2 == 1) gsub(/,/, OFS, a[i])
    else a[i] = (q a[i] q)
    out = (out) ? out a[i] : a[i]}
  return out}
{c=split($0, a, q); out=X;
  if(a[1]) $0=csv2del(1)
  else $0=csv2del(2)}1' OFS='|' file
Srini
источник