Чи є надійний інструмент командного рядка для обробки файлів 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

Моє остаточне рішення було в пітоні, оскільки мій Perl був занадто іржавим. Дякую.
Стівен Д

2
Ще краще, використовуйте Pandas . Він явно призначений для роботи з табличними даними.
Джош

38

Я, мабуть, трохи пізно, але є ще один інструмент, який варто згадати: csvkit

http://csvkit.readthedocs.org/

У ньому багато інструментів командного рядка, які можуть:

  • переформатування файлів CSV,
  • конвертувати в CSV і з нього з різних форматів (JSON, SQL, XLS),
  • еквівалент cut, grep, sortта інші, але CSV-відомо,
  • приєднуйтесь до різних файлів CSV,
  • робити загальні запити SQL щодо даних з файлів CSV.

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.
Stéphane Chazelas

Я вважаю. Хоча розбивання більше двох рядків на 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:

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чи подібне.
Faheem Mitha

Ага так. Я досить досвідчений в 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 і не можу підтвердити, що це справно працює, і як це зробити.


9
Ось один awk CSV Parser, який я використовував деякий час назад .. Здається, досить добре продуманий ... lorance.freeshell.org/csv
Peter.O



2

спробуйте "csvtool" цей пакет - це зручний інструмент командного рядка для обробки файлів CSV


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

1

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


2
Ви б не хотіли розмістити якийсь зразок коду, наприклад відповіді Perl, Python та R? (Тим більше, що Керрі не є загальною мовою сценаріїв Unix.)
Жил "SO- перестань бути злим"

@Gilles: Так, ти маєш рацію, я мушу опублікувати зразок коду, щоб покращити відповідь. Я збираюся це зробити через деякий час.
imz - Іван Захарящев

1

Інструменти для структурованого тексту github repo мають корисний перелік відповідних інструментів командного рядка Linux. Зокрема, у розділі розділених значень роздільника перелічено декілька інструментів, що підтримують CSV, які безпосередньо підтримують запитувані операції.



1

Один з найкращих інструментів - Міллер ( http://johnkerl.org/miller/doc/index.html ). Це як awk, sed, cut, join, sorting для даних, індексованих іменами, такими як 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"

1

Якщо ви хочете візуальний / інтерактивний інструмент в терміналі, я від щирого серця рекомендую VisiData.

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

Він має таблиці частот (показано вище), повороти, плавки, розсіювачі, фільтрація / обчислення за допомогою Python та ін.

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

vd hello.csv

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


0

Шикарне рішення

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.