มีเครื่องมือบรรทัดคำสั่งที่แข็งแกร่งสำหรับการประมวลผลไฟล์ 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 ของฉันเป็นสนิมเกินไป ขอบคุณ
Steven D

2
ยิ่งไปกว่านั้นใช้นุ่น มันถูกออกแบบมาอย่างชัดเจนเพื่อทำงานกับข้อมูลตาราง
Josh

38

ฉันอาจจะสายไปหน่อย แต่ก็มีเครื่องมืออีกอย่างที่ควรค่าแก่การกล่าวถึง: csvkit

http://csvkit.readthedocs.org/

มันมีเครื่องมือบรรทัดคำสั่งมากมายที่สามารถ:

  • ฟอร์แมตไฟล์ CSV
  • แปลงเป็นและจาก CSV จากรูปแบบต่าง ๆ (JSON, SQL, XLS)
  • เทียบเท่าcut, grep, sortและคนอื่น ๆ แต่ CSV ทราบ
  • เข้าร่วมไฟล์ CSV ที่แตกต่างกัน
  • ทำแบบสอบถาม SQL ทั่วไปเกี่ยวกับข้อมูลจากไฟล์ CSV

6
เครื่องมือที่ยอดเยี่ยมที่ตรงตามเกณฑ์คำถามอย่างยอดเยี่ยม (โดยเฉพาะอย่างยิ่งมันไม่จำเป็นต้องกระโดดเข้าสู่ภาษาการเขียนโปรแกรม
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];
'

ดูเอกสารประกอบสำหรับวิธีจัดการกับชื่อคอลัมน์ คั่นและ quoting newสไตล์สามารถปรับด้วยพารามิเตอร์ ดูเพิ่มเติมText::CSV::Separatorสำหรับการเดาตัวคั่น


มีซับหนึ่งที่คุณสามารถบีบอัดให้เป็นนี้หรือไม่ ฉันชอบ Perl แต่เมื่อฉันสามารถเรียกได้โดยตรงจากบรรทัดคำสั่งมากกว่ากับสคริปต์
Sridhar Sarnobat

2
@ user7000 ยกเว้นว่าเชลล์ของคุณคือ(t)cshคำสั่งนั้นจะทำงานได้ดีที่พร้อมต์ของเชลล์ คุณสามารถรวมเส้นเหล่านั้นเข้าด้วยกันได้หากคุณต้องการในบรรทัดเดียว ขึ้นบรรทัดใหม่โดยทั่วไปเช่นเดียวกับพื้นที่ในไวยากรณ์ Perl เช่นใน C.
Stéphane Chazelas

ฉันคิดว่า. แม้ว่าการบีบมากกว่า 2 บรรทัดใน 1 ไม่ใช่สิ่งที่ฉันหมายถึงโดยสายการบินเดียว ฉันหวังว่าจะมีน้ำตาล syntactic ที่จะทำบางอย่างโดยปริยาย (เช่นวิธีการ-eสร้างวงโดยปริยาย)
Sridhar Sarnobat

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
Steven D

1
@Steven: R สามารถรันได้ง่ายจากบรรทัดคำสั่งในแบบเดียวกับ Python หรือ Perl ถ้าเป็นเรื่องเดียวที่คุณกังวล ดูRscript(ส่วนหนึ่งของการกระจายฐาน R) หรือแพ็คเกจlittlerเสริม คุณสามารถทำได้#!/usr/bin/env Rscriptหรือคล้ายกัน
Faheem Mitha

อ่าใช่ ฉันค่อนข้างเชี่ยวชาญใน R แต่ไม่ได้ใช้มากนักในการสร้างโปรแกรมอรรถประโยชน์ประเภทนี้ ฉันมีสิ่งที่ทำงานใน Python แต่ฉันอาจลองสร้างบางสิ่งใน R เช่นกัน
Steven D


4

มิลเลอร์เป็นอีกหนึ่งเครื่องมือที่ดีสำหรับการจัดการข้อมูลตามชื่อรวมถึง CSV (พร้อมส่วนหัว) หากต้องการแยกคอลัมน์แรกของไฟล์ CSV โดยไม่สนใจชื่อของมันคุณต้องทำอะไรเช่นนี้

printf '"first,column",second,third\n1,2,3\n' |
  mlr --csv --implicit-csv-header --headerless-csv-output cut -f 1

มิลเลอร์น่าประทับใจมาก ฉันจะเปรียบเทียบกับawkแต่ทราบดีถึง DSV
Derek Mahar

3

หรือคุณอาจลองใช้เวทย์มนตร์awk อย่างไรก็ตามฉันไม่ใช่ผู้ใช้ awk ที่ดีและไม่สามารถยืนยันได้ว่าจะทำงานได้อย่างถูกต้องและวิธีการทำ


9
นี่คือหนึ่งใน CSV Parser awk ที่ฉันใช้ในขณะที่กลับมา .. ดูเหมือนว่าค่อนข้างดีคิดออก ... lorance.freeshell.org/csv
Peter.O



2

ลอง "csvtool" แพคเกจนี้มันเป็นเครื่องมือบรรทัดคำสั่งที่มีประโยชน์สำหรับการจัดการไฟล์ CSV


1
มีการพูดถึงรายละเอียดเพิ่มเติมแล้ว ...
jasonwryan

2

cissyจะทำการประมวลผล csv บรรทัดคำสั่ง มันเขียนใน C (ขนาดเล็ก / น้ำหนักเบา) พร้อม rpm และ deb แพ็คเกจที่พร้อมใช้งานสำหรับ distros ส่วนใหญ่

ใช้ตัวอย่าง:

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

นอกจากนี้ยังมีแกงห้องสมุดสำหรับการอ่าน / เขียนไฟล์ในรูปแบบ CSV: CSV


2
คุณต้องการโพสต์โค้ดตัวอย่างเช่นคำตอบ Perl, Python และ R หรือไม่? (โดยเฉพาะอย่างยิ่งเนื่องจาก Curry ไม่ใช่ภาษาสคริปต์ยูนิกซ์ทั่วไป)
Gilles 'ดังนั้น - หยุดความชั่วร้าย'

@Gilles: ใช่คุณพูดถูกฉันควรโพสต์โค้ดตัวอย่างเพื่อให้คำตอบดีขึ้น ฉันจะทำเช่นนี้ในขณะที่
imz - Ivan Zakharyaschev

1

เครื่องมือข้อความโครงสร้าง github repo มีรายการเครื่องมือบรรทัดคำสั่ง linux ที่เกี่ยวข้อง โดยเฉพาะอย่างยิ่งส่วนค่าคั่นคั่นแสดงรายการเครื่องมือที่มีความสามารถ CSV หลายอย่างที่สนับสนุนการดำเนินการที่ร้องขอโดยตรง



1

หนึ่งในเครื่องมือที่ดีที่สุดคือมิลเลอร์ ( http://johnkerl.org/miller/doc/index.html ) มันเหมือนกับ awk, sed, cut, join และเรียงลำดับสำหรับข้อมูลที่จัดทำดัชนีชื่อเช่น 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

หากคุณต้องการเครื่องมือแสดงผล / โต้ตอบใน terminal ฉันขอแนะนำ VisiData อย่างเต็มที่

ป้อนคำอธิบายรูปภาพที่นี่

มันมีตารางความถี่ (แสดงด้านบน), pivot, ละลาย, scatterplots, การกรอง / การคำนวณโดยใช้ Python และอื่น ๆ

คุณสามารถส่งไฟล์ csv ได้

vd hello.csv

มีตัวเลือกที่เฉพาะเจาะจง CSV คือ: --csv-dialect, --csv-delimiter, --csv-quotecharและ--csv-skipinitialspaceสำหรับการปรับการจัดการไฟล์ CSV


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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.