कैसे बैश में एक सीएसवी फ़ाइल पार्स करने के लिए?


112

मैं एक लंबी बैश स्क्रिप्ट पर काम कर रहा हूं। मैं सीएसवी फ़ाइल से बैश चर में कोशिकाओं को पढ़ना चाहता हूं। मैं लाइनों और पहले कॉलम को पार्स कर सकता हूं, लेकिन किसी अन्य कॉलम को नहीं। यहाँ मेरा कोड अब तक है:


  cat myfile.csv|while read line
  do
    read -d, col1 col2 < <(echo $line)
    echo "I got:$col1|$col2"
  done

यह केवल पहला कॉलम छाप रहा है। एक अतिरिक्त परीक्षण के रूप में, मैंने निम्नलिखित कोशिश की:

read -d, x y < <(echo a,b,)

और $ य खाली है। इसलिए मैंने कोशिश की:

read x y < <(echo a b)

और $ य है b। क्यों?


7
आप पर विचार किया है awkउपयोग करने के लिए $1, $2, आदि?
BeemerGuy

4
एक विचार के रूप में: कमांड <<(इको "स्ट्रिंग") ---> कमांड <<< "स्ट्रिंग"
टोकन

1
'कट' कमांड लाइन कार्यक्रम उस के लिए डिज़ाइन किया गया था: ss64.com/bash/cut.html
Jay

जवाबों:


215

आपको IFSइसके बजाय उपयोग करने की आवश्यकता है -d:

while IFS=, read -r col1 col2
do
    echo "I got:$col1|$col2"
done < myfile.csv

ध्यान दें कि सामान्य प्रयोजन के लिए CSV पार्सिंग के लिए आपको एक विशेष उपकरण का उपयोग करना चाहिए, जो कि अन्य क्षेत्रों में आंतरिक कॉमा के साथ उद्धृत फ़ील्ड्स को संभाल सकता है, जो कि बैश खुद से नहीं संभाल सकता है। ऐसे औजारों के उदाहरण हैं cvstoolऔर csvkit


7
प्रस्तावित समाधान बहुत ही सरल CSV फ़ाइलों के लिए ठीक है, अर्थात्, यदि हेडर और मान अल्पविराम और एम्बेडेड उद्धरण चिह्नों से मुक्त हैं। यह वास्तव में एक सामान्य CSV पार्सर लिखने के लिए काफी मुश्किल है (विशेषकर चूंकि कई CSV "मानक" हैं)। CSV फ़ाइलों को * nix टूल के लिए अधिक उपयोगी बनाने के लिए एक दृष्टिकोण उन्हें TSV (टैब-अलग किए गए मान) में बदलना है, जैसे Excel का उपयोग करना।
चोटी

यह दिलचस्प है कि मैं शरीर में mkdir नहीं कर सकता। मुझे मिल रहा है command not found। केवल echoकाम करता है।
Zsolt

1
@Zsolt: ऐसा कोई कारण नहीं है कि मामला होना चाहिए। आपके पास टाइपो या आवारा गैर-मुद्रण वर्ण होना चाहिए।
अगली सूचना तक रोक दिया गया।

2
@DennisWilliamson का उपयोग करते समय आपको सेपरेटर को संलग्न करना चाहिए ;:while IFS=";" read col1 col2; do ...
thomas.mc.work

1
@ thomas.mc.work: यह अर्धविराम और अन्य वर्णों के मामले में सच है जो शेल के लिए विशेष हैं। अल्पविराम के मामले में, यह आवश्यक नहीं है और मैं उन पात्रों को छोड़ना पसंद करता हूं जो अनावश्यक हैं। उदाहरण के लिए, आप घुंघराले ब्रेसिज़ (उदाहरण ${var}) का उपयोग करके हमेशा विस्तार के लिए चर निर्दिष्ट कर सकते हैं , लेकिन जब आवश्यक नहीं हो तो मैं उन्हें छोड़ देता हूं। मेरे लिए, यह साफ दिखता है।
अगली सूचना तक रोक दिया गया।

10

से manपेज:

-d delim नई लाइन के बजाय, डेलिम के पहले वर्ण का उपयोग इनपुट लाइन को समाप्त करने के लिए किया जाता है।

आप उपयोग कर रहे हैं -d,जो अल्पविराम पर इनपुट लाइन को समाप्त कर देगा। यह शेष पंक्ति को नहीं पढ़ेगा। इसलिए $ य खाली है।


3

हम उद्धृत स्ट्रिंग और सीमांकित के साथ सीएसवी फ़ाइलों को पार्स कर सकते हैं | निम्नलिखित कोड के साथ

while read -r line
do
    field1=$(echo $line | awk -F'|' '{printf "%s", $1}' | tr -d '"')
    field2=$(echo $line | awk -F'|' '{printf "%s", $2}' | tr -d '"')

    echo $field1 $field2
done < $csvFile

awk parse स्ट्रिंग फ़ील्ड्स को वैरिएबल में विभाजित करता है और tr उद्धरण निकालता है।

प्रत्येक क्षेत्र के लिए awk के रूप में थोड़ा धीमा निष्पादित होता है।


1
अच्छा, आप कोमा (,)
pkarc

0

यदि आप कुछ पंक्तियों के साथ CSV फ़ाइल पढ़ना चाहते हैं, तो यह समाधान है।

while IFS=, read -ra line
do 
    test $i -eq 1 && ((i=i+1)) && continue
    for col_val in ${line[@]}
    do
        echo -n "$col_val|"                 
    done
    echo        
done < "$csvFile"
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.