2010-03-29 11 views
36

में सीएसवी में कनवर्ट करें। मेरे पास एक टैब-डिलीमिट फ़ाइल है जिसमें 200 मिलियन से अधिक लाइनें हैं। लिनक्स में इसे एक सीएसवी फ़ाइल में बदलने के लिए सबसे तेज़ तरीका क्या है? इस फ़ाइल में हेडर जानकारी की कई पंक्तियां हैं जिन्हें मुझे सड़क से बाहर करने की आवश्यकता होगी, लेकिन शीर्षलेख की पंक्तियों की संख्या ज्ञात है। मैंने sed और gawk के लिए सुझाव देखे हैं, लेकिन मुझे आश्चर्य है कि "पसंदीदा" विकल्प है या नहीं।सबसे तेज़ तरीका टैब-डिलीमिटेड फ़ाइल को लिनक्स

बस स्पष्ट करने के लिए, इस फ़ाइल में कोई एम्बेडेड टैब नहीं हैं।

+0

tsv और एम्बेडेड सीमांकक मुद्दों के लिए सीएसवी के लिए, यह भी http://stackoverflow.com/questions/13475535/replace-every-comma-not-enclosed-in-a-pair-of-double के उत्तर देख -क्वॉट्स के साथ (प्रासंगिक भी: http://unix.stackexchange.com/questions/48672/remove-comma-between-the-quotes-only-in-a-comma-delimited-file)। –

उत्तर

38

यदि आपको केवल अनुवाद करना है तो सभी टैब वर्णों को अल्पविराम वर्णों के लिए, tr संभवतः जाने का तरीका है।

यहां खाली जगह एक शाब्दिक टैब है:

$ echo "hello world" | tr "\\t" "," 
hello,world 
बेशक

, यदि आप फ़ाइल में स्ट्रिंग शाब्दिक अंदर टैब एम्बेडेड है, यह गलत तरीके से उन लोगों के रूप में अच्छी तरह से अनुवाद कर देगा; लेकिन एम्बेडेड शाब्दिक टैब काफी असामान्य होंगे।

+13

स्रोत में एम्बेडेड कॉमा अधिक आम हैं, जिसके बाद उद्धरण के साथ रैपिंग की आवश्यकता होती है। एम्बेडेड कोट्स होने पर परेशानी होती है ... – kibibu

+0

'tr' सुझाव के लिए धन्यवाद। यह गति के साथ 'sed' की तुलना कैसे करता है? मान लीजिए कि आप हेडर स्टार्ट को लाइन नंबर एक्स पर छोड़ना चाहते हैं और बाकी फाइल को जारी रखना चाहते हैं। क्या इसे 'tr' के साथ कार्यान्वित करने का कोई तरीका है? (मुझे यह भी स्पष्ट करना चाहिए कि फ़ाइल में कोई एम्बेडेड कॉमा नहीं है।) – andrewj

+0

@andrewj: 'tr' बहुत तेज होना चाहिए, क्योंकि यह रेगेक्स मिलान के बजाय चरित्र-दर-चरित्र प्रतिस्थापन कर रहा है। हेडर छोड़ने के लिए, सबसे आसान बात सिर्फ दो हिस्सों में संसाधित करना है - यदि आप लंबाई जानते हैं, तो 'head -n इनपुट> आउटपुट; tail -n + इनपुट | tr ... >> आउटपुट'; यदि आपको लंबाई नहीं पता है, शायद 'grep -n' के साथ कुछ ... – Cascabel

62

यदि आप एम्बेडेड कॉमा के बारे में चिंतित हैं तो आपको थोड़ा और बुद्धिमान विधि का उपयोग करने की आवश्यकता होगी।

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 
+1

जब तक आप यह सुनिश्चित करने के लिए नहीं जानते कि कोई एम्बेडेड कॉमा नहीं है और कोई एम्बेडेड टैब नहीं है, तो यह करने का यह एक बहुत ही विश्वसनीय तरीका है। भले ही यह शायद 'सबसे तेज़' होने के मानदंडों को पूरा न करे। – leedm777

+2

यह "सबसे तेज़" नहीं हो सकता है, लेकिन यह मेरे लिए एम्बेडेड टैब और कॉमा को संभालता है। – anshuman

+1

यह चट्टानों। मैं बैश में इसका ख्याल रखने के लिए एक क्रिप्टिक सेड स्क्रिप्ट लिख रहा था - लेकिन वह अजगर सीएसवी लाइब्रेरी की पूर्णता के साथ प्रतिस्पर्धा नहीं कर सकता है। इस पेशकश के लिए, Ignacio धन्यवाद। गति के बारे में - उपयोग की आसानी और उपयोग की गति की गति की गति - यह निश्चित रूप से पर्याप्त तेज़ है। :-) – dlink

3

मानते हुए कि आपके हेडर बदलने के लिए नहीं करना चाहते हैं और यह मानते हुए यहां Python स्क्रिप्ट है जो stdout को stdin से TSV लाइनों लेता है और सीएसवी लाइनों लिखते है आपके पास एम्बेडेड टैब नहीं हैं

# cat file 
header header header 
one  two  three 

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

एनआर> 1 पहला हेडर छोड़ देता है। आपने बताया है कि आप जानते हैं कि शीर्षलेख की कितनी पंक्तियां हैं, इसलिए अपने स्वयं के मामले के लिए सही संख्या का उपयोग करें। इसके साथ, आपको किसी अन्य बाहरी आदेश को कॉल करने की आवश्यकता नहीं है। सिर्फ एक अजीब कमांड नौकरी करता है।

यदि आपके पास खाली कॉलम हैं और आप इसकी परवाह करते हैं तो एक और तरीका है।

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

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 

आलोचकों लानत है, बोली सब कुछ, सीएसवी परवाह नहीं है।

<tab> वास्तविक टैब वर्ण है। \ t मेरे लिए काम नहीं किया। बैश में, इसे दर्ज करने के लिए^वी का उपयोग करें।

+0

टैब, आप 'sed -e'///\\ "/ g '-e" s/\ t/\ ", \"/g "-e'/^ /"/'-e' कर सकते हैं/$/"/ 'infile> outfile'। –

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

पर्ल sed, awk, और अजगर से बात की इस तरह से आम तौर पर तेजी है।

+1

मेरे लिए सबसे अच्छा जवाब, केवल एक छोटा सा परिवर्तन, डबल कोट्स स्कैप: perl -lpe's /"/\\ "/ g; s/^ | $ /"/g; एस/\ टी/","/जी '<... – Lix

+0

लंबे समय तक लाइव पर्ल! वास्तव में एक लाइनर जो मुझे चाहिए। – Debriter

+0

आप एक उद्धारकर्ता – Yankee

0

निम्नलिखित 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"""" 
4

@ Ignacio-वेज़क्वेज़-अब्राम के अजगर समाधान बहुत अच्छा है! उन लोगों के लिए जो डिलीमीटर अन्य टैब को पार्स करने के लिए देख रहे हैं, लाइब्रेरी वास्तव में आपको मनमाने ढंग से डिलीमीटर सेट करने की अनुमति देती है।

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

  • यदि आप चाहते हैं: आप एक csv फ़ाइल में पूरी TSV फ़ाइल कन्वर्ट करने के लिए चाहते हैं

    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
    • : यहाँ पाइप-सीमांकित फ़ाइलों को संभालने के लिए अपने संशोधित संस्करण है कुछ क्षेत्रों को छोड़ने के लिए:

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

      उपरोक्त आदेश data.tsv फ़ाइल को data.csv फ़ाइल में परिवर्तित करेगा जिसमें केवल पहले तीन फ़ील्ड शामिल हैं।

    +1

    बहुत अच्छे हैं :) –

    संबंधित मुद्दे