सीएसवी फ़ाइल के एक कॉलम को कैसे निकाला जाए


111

अगर मेरे पास एक सीएसवी फ़ाइल है, तो क्या किसी एकल कॉलम की सामग्री को प्रिंट करने का एक त्वरित तरीका है? यह मान लेना सुरक्षित है कि प्रत्येक पंक्ति में समान स्तंभ हैं, लेकिन प्रत्येक स्तंभ की सामग्री की लंबाई अलग-अलग होगी।

जवाबों:


136

आप इसके लिए awk का उपयोग कर सकते हैं। Change $ 2 ’को अपने इच्छित nth कॉलम में बदलें।

awk -F "\"*,\"*" '{print $2}' textfile.csv

13
echo '1,"2,3,4,5",6' | awk -F "\"*,\"*" '{print $2}'के 2बजाय मुद्रित करेगा 2,3,4,5
इगोर मिकुश्किन

यदि आप विंडोज में GNU टूल्स का उपयोग करने वाले एक भाग्यशाली व्यक्ति हैं, तो आप एक ही कॉमैंड को @IgorMikushkin के रूप में निष्पादित कर सकते हैं:gawk -F"|" "{print $13}" files*.csv
एलिडियो मारकिना

10
मुझे लगता है कि यह तब विफल होता है जब ऐसे तार होते हैं जिनमें कॉमा होता है, अर्थात...,"string,string",...
सोडियमनाइट्रेट

मुझे लगता है कि पहली और आखिरी कॉलुम के लिए, यह कुछ दोष होगा। पहले कॉलम के साथ शुरू होगा "और आखिरी के साथ समाप्त होगा"
BigTailWolf

कुछ प्रोग्राम अलग-अलग सीमांकक के साथ CSV फ़ाइलों को लौटाते हैं, इसलिए इसके अनुसार नियमित अभिव्यक्ति को बदलने की आवश्यकता हो सकती है। एक अर्धविराम सीमांकक के लिए उदाहरण: awk -F "\"*;\"*" '{print $2}' textfile.csv
gekkedev

88

हाँ। cat mycsv.csv | cut -d ',' -f33 कॉलम प्रिंट करेगा।


8
जब तक कॉलम दो में एक अल्पविराम नहीं होता है, तब तक आपको कॉलम दो का दूसरा भाग मिलेगा। बिंदु में मामला <col1>, "3,000", <col2>। उस समस्या के संबंध में मेरा जवाब बहुत बेहतर नहीं है। तो बाहर bummed मत बनो।
सिंथेसाइजरपटेल


1
हमें यकीन नहीं है कि उनकी CSV फ़ाइल में विभिन्न मूल्यों को अलग करने के लिए युगल उद्धरण हैं। यह बेहतर होगा कि वह एक इनपुट फ़ाइल प्रदान करें ताकि हम सबसे उपयुक्त समाधान का आकलन कर सकें।
इदरीस न्यूमैन

51

सबसे आसान तरीका है कि मैं इसे पूरा करने में सक्षम था बस csvtool का उपयोग करें । मेरे पास अन्य उपयोग के मामले के साथ-साथ सीएसवेटूल का उपयोग करने के लिए भी था और यह कॉलम या सीमांकक को उचित रूप से संभाल सकता है यदि वे कॉलम डेटा के भीतर दिखाई देते हैं।

csvtool format '%(2)\n' input.csv

कॉलम नंबर के साथ 2 की जगह प्रभावी रूप से आपके द्वारा खोजे जा रहे कॉलम डेटा को निकाल देगा।


14
यह स्वीकृत उत्तर होना चाहिए। यह उपकरण जानता है कि CSV फ़ाइलों से कैसे निपटा जाए, साथ ही एक क्षेत्र विभाजक के रूप में अल्पविराम का इलाज करना। 2 कॉलम निकालने के लिए, "csvtool col 2 input.csv"
व्लादिस्लाव्स डोवलगेक्स

3
बस एक सिर ... यदि आप मानक इनपुट के साथ सीएसवेटूल का उपयोग करना चाहते हैं (उदाहरण सीएसवी एक अन्य कमांड से आता है) यह कुछ इस तरह है cat input.csv | csvtool formath '%(2)\n' -नोट मुझे पता है कि बिल्ली यहां बेकार है, लेकिन इसे किसी भी कमांड के लिए उप है जो सामान्य रूप से सीएसवी निर्यात करेगा।
जनरल रेडनेक

यह मल्टीलाइन फ़ील्ड हैं, format '%(2)\n'कमांड यह नहीं बता सकता कि एक फ़ील्ड कहाँ समाप्त होती है। (csvtool 1.4.2)
जारो

1
नए संस्करणों को स्टड से पढ़ने के लिए इनपुट फ़ाइल नाम के रूप में csvtoolउपयोग करने की आवश्यकता प्रतीत होती है -
कॉनर क्लार्क

@GeneralRedneck बिल्ली का उपयोग क्यों करें? और यह प्रारूप नहीं हैcsvtool format '%(1),%(10)\n' - < in.csv > out.csv
sijanec

14

यहाँ एक अलग फ़ाइल से टैब निकालने की तलाश में। सोचा था कि जोड़ दूंगा।

cat textfile.tsv | cut -f2 -s

जहां -f22, गैर-शून्य अनुक्रमित स्तंभ, या दूसरा कॉलम निकालता है।


सरल, बहुत अधिक बिंदु, और अन्य उदाहरणों की तुलना में अधिक आसानी से अनुकूलनीय। धन्यवाद!
निक जेनिंग्स

6
नाइटपैकिंग, लेकिन catअनावश्यक है:< textfile.tsv cut -f2 -s
ऐनी वैन

8

इस प्रश्न के कई उत्तर महान हैं और कुछ ने तो कोने के मामलों में भी देखा है। मैं एक सरल उत्तर जोड़ना चाहूंगा जो दैनिक उपयोग का हो सकता है ... जहां आप ज्यादातर उन कोने के मामलों में आते हैं (जैसे कि उद्धरणों में अल्पविराम या अल्पविराम से बचना आदि)।

FS (फील्ड सेपरेटर) वह चर है जिसका मान अंतरिक्ष में dafaulted है। इसलिए किसी भी लाइन के लिए स्पेस में डिफॉल्ट स्प्लिट्स से जागना।

इसलिए BEGIN (इनपुट लेने से पहले Execute) का उपयोग करके हम इस क्षेत्र को अपनी इच्छानुसार कुछ भी सेट कर सकते हैं ...

awk 'BEGIN {FS = ","}; {print $3}'

उपरोक्त कोड csv फ़ाइल में 3rd कॉलम प्रिंट करेगा।


1
मैंने यह कोशिश की है, और यह अभी भी उद्धृत क्षेत्रों के अंदर अल्पविराम मानता है।
डैनियल सी। सोबरल

5

अन्य उत्तर अच्छी तरह से काम करते हैं, लेकिन चूंकि आपने बस बैश शेल का उपयोग करके समाधान के लिए कहा है, आप ऐसा कर सकते हैं:

AirBoxOmega:~ d$ cat > file #First we'll create a basic CSV
a,b,c,d,e,f,g,h,i,k
1,2,3,4,5,6,7,8,9,10
a,b,c,d,e,f,g,h,i,k
1,2,3,4,5,6,7,8,9,10
a,b,c,d,e,f,g,h,i,k
1,2,3,4,5,6,7,8,9,10
a,b,c,d,e,f,g,h,i,k
1,2,3,4,5,6,7,8,9,10
a,b,c,d,e,f,g,h,i,k
1,2,3,4,5,6,7,8,9,10
a,b,c,d,e,f,g,h,i,k
1,2,3,4,5,6,7,8,9,10

और फिर आप कॉलम को बाहर निकाल सकते हैं (इस उदाहरण में पहला) जैसे:

AirBoxOmega:~ d$ while IFS=, read -a csv_line;do echo "${csv_line[0]}";done < file
a
1
a
1
a
1
a
1
a
1
a
1

इसलिए यहां कुछ चीजें चल रही हैं:

  • while IFS=,- यह IFS (आंतरिक क्षेत्र विभाजक) के रूप में अल्पविराम का उपयोग करने के लिए कह रहा है, जो कि शेल का उपयोग करता है यह जानने के लिए कि फ़ील्ड (पाठ के ब्लॉक) को अलग करता है। तो IFS = कह रहा है, "A, b" के समान है, "B a" जैसा होगा यदि IFS = "" होगा (जो कि डिफ़ॉल्ट रूप से यही है।)

  • read -a csv_line; - यह कह रहा है कि प्रत्येक पंक्ति में पढ़ा जाता है, एक समय में एक और एक सरणी बनाएं जहां प्रत्येक तत्व को "csv_line" कहा जाता है और इसे लूप करते समय हमारे "अनुभाग" के लिए भेजें।

  • do echo "${csv_line[0]}";done < file- अब हम "do" चरण में हैं, और हम सरणी के 0 वें तत्व "csv_line" को प्रतिध्वनित कर रहे हैं। यह क्रिया फ़ाइल की प्रत्येक पंक्ति पर दोहराई जाती है। < fileहिस्सा सिर्फ जहां से पढ़ने के लिए है, जबकि पाश कह रहा है। नोट: याद रखें, बाश में, सरणियाँ 0 अनुक्रमित हैं, इसलिए पहला स्तंभ 0 तत्व है।

तो वहाँ आप यह है, खोल में एक CSV से एक स्तंभ बाहर खींच। अन्य समाधान शायद अधिक व्यावहारिक हैं, लेकिन यह एक शुद्ध बैश है।


5

आप GNU Awk का उपयोग कर सकते हैं, उपयोगकर्ता गाइड के इस लेख को देखें । लेख में प्रस्तुत समाधान में सुधार के रूप में (जून 2015 में), निम्न गॉक कमांड दोहरे उद्धृत क्षेत्रों के अंदर दोहरे उद्धरण चिह्नों की अनुमति देता है; एक दोहरे उद्धरण को दो लगातार दोहरे उद्धरण चिह्नों ("") द्वारा चिह्नित किया जाता है। इसके अलावा, यह खाली फ़ील्ड की अनुमति देता है, लेकिन यहां तक ​​कि यह मल्टीलाइन फ़ील्ड को संभाल नहीं सकता है । निम्न उदाहरण c=3textfile.csv के तीसरे स्तंभ (के माध्यम से ) को प्रिंट करता है :

#!/bin/bash
gawk -- '
BEGIN{
    FPAT="([^,\"]*)|(\"((\"\")*[^\"]*)*\")"
}
{
    if (substr($c, 1, 1) == "\"") {
        $c = substr($c, 2, length($c) - 2) # Get the text within the two quotes
        gsub("\"\"", "\"", $c)  # Normalize double quotes
    }
    print $c
}
' c=3 < <(dos2unix <textfile.csv)

ध्यान से dos2unixसंभव डॉस स्टाइल लाइन ब्रेक (CRLF यानी "\ r \ n") और UTF-16 एन्कोडिंग (बाइट ऑर्डर मार्क के साथ) को "\ n" और UTF-8 (बाइट ऑर्डर मार्क के बिना) के उपयोग पर ध्यान दें। मानक CSV फाइलें लाइन ब्रेक के रूप में CRLF का उपयोग करती हैं, विकिपीडिया देखें ।

यदि इनपुट में मल्टीलाइन फ़ील्ड हो सकते हैं, तो आप निम्न स्क्रिप्ट का उपयोग कर सकते हैं। आउटपुट में रिकॉर्ड को अलग करने के लिए विशेष स्ट्रिंग के उपयोग पर ध्यान दें (चूंकि डिफ़ॉल्ट विभाजक न्यूलाइन रिकॉर्ड के भीतर हो सकता है)। फिर से, निम्न उदाहरण c=3textfile.csv के तीसरे कॉलम (के माध्यम से ) को प्रिंट करता है :

#!/bin/bash
gawk -- '
BEGIN{
    RS="\0" # Read the whole input file as one record;
    # assume there is no null character in input.
    FS="" # Suppose this setting eases internal splitting work.
    ORS="\n####\n" # Use a special output separator to show borders of a record.
}
{
    nof=patsplit($0, a, /([^,"\n]*)|("(("")*[^"]*)*")/, seps)
    field=0;
    for (i=1; i<=nof; i++){
        field++
        if (field==c) {
            if (substr(a[i], 1, 1) == "\"") {
                a[i] = substr(a[i], 2, length(a[i]) - 2) # Get the text within 
                # the two quotes.
                gsub(/""/, "\"", a[i])  # Normalize double quotes.
            }
            print a[i]
        }
        if (seps[i]!=",") field=0
    }
}
' c=3 < <(dos2unix <textfile.csv)

समस्या का एक और तरीका है। csvquote एक CSV फ़ाइल की सामग्री को संशोधित कर सकता है ताकि क्षेत्र के भीतर विशेष वर्ण रूपांतरित हो जाएं ताकि कुछ कॉलम चुनने के लिए सामान्य रूप से यूनिक्स टेक्स्ट प्रोसेसिंग टूल का उपयोग किया जा सके। उदाहरण के लिए निम्नलिखित कोड तीसरा कॉलम आउटपुट करता है:

csvquote textfile.csv | cut -d ',' -f 3 | csvquote -u

csvquote बड़ी फ़ाइलों को मनमाने ढंग से संसाधित करने के लिए इस्तेमाल किया जा सकता है।


5

यहां 2 कॉलम के साथ एक सीएसवी फ़ाइल उदाहरण है

myTooth.csv

Date,Tooth
2017-01-25,wisdom
2017-02-19,canine
2017-02-24,canine
2017-02-28,wisdom

पहला कॉलम पाने के लिए, उपयोग करें:

cut -d, -f1 myTooth.csv

f का मतलब फ़ील्ड है और d का मतलब सीमांकक है

उपरोक्त कमांड चलाने से निम्नलिखित आउटपुट उत्पन्न होंगे।

उत्पादन

Date
2017-01-25
2017-02-19
2017-02-24
2017-02-28

केवल दूसरा कॉलम पाने के लिए:

cut -d, -f2 myTooth.csv

और यहाँ आउटपुट आउटपुट है

Tooth
wisdom
canine
canine
wisdom
incisor

एक अन्य उपयोग मामला:

आपकी सीएसवी इनपुट फ़ाइल में 10 कॉलम होते हैं और आप कॉलम 2 को 5 और कॉलम 8 से, कॉमा को विभाजक के रूप में उपयोग करना चाहते हैं "।

विभाजकों को निर्दिष्ट करने के लिए कॉलम और -d (जिसका अर्थ "सीमांकक") निर्दिष्ट करने के लिए कट-ऑफ (जिसका अर्थ "फ़ील्ड") है। आपको बाद वाले को निर्दिष्ट करने की आवश्यकता है क्योंकि कुछ फाइलें स्तंभों को अलग करने के लिए रिक्त स्थान, टैब या कॉलोन का उपयोग कर सकती हैं।

cut -f 2-5,8 -d , myvalues.csv

कट एक कमांड उपयोगिता है और यहां कुछ और उदाहरण दिए गए हैं:

SYNOPSIS
     cut -b list [-n] [file ...]
     cut -c list [file ...]
     cut -f list [-d delim] [-s] [file ...]

4

मुझे उचित CSV पार्सिंग की आवश्यकता थी, न कि cut/ awkऔर प्रार्थना की। मैं इस पर एक कोशिश कर रहा हूँ MAC बिना csvtool, लेकिन macs माणिक के साथ आते हैं, तो आप कर सकते हैं:

echo "require 'csv'; CSV.read('new.csv').each {|data| puts data[34]}" | ruby

4

पहले हम एक बुनियादी CSV बनाएंगे

[dumb@one pts]$ cat > file 
a,b,c,d,e,f,g,h,i,k  
1,2,3,4,5,6,7,8,9,10  
a,b,c,d,e,f,g,h,i,k  
1,2,3,4,5,6,7,8,9,10

तब हमें 1st कॉलम मिलता है

[dumb@one pts]$  awk -F , '{print $1}' file  
a  
1  
a  
1

3
csvtool col 2 file.csv 

जहां 2 वह कॉलम है जिसमें आप रुचि रखते हैं

आप भी कर सकते हैं

csvtool col 1,2 file.csv 

कई कॉलम करने के लिए


3

मुझे लगता है कि सबसे आसान csvkit का उपयोग कर रहा है :

दूसरा स्तंभ हो जाता है: csvcut -c 2 file.csv

हालांकि, वहाँ भी csvtool है , और शायद वहाँ से बाहर अन्य csv bash उपकरण की एक संख्या है:

sudo apt-get install csvtool (डेबियन आधारित प्रणालियों के लिए)

इससे पहली पंक्ति में एक कॉलम होगा जिसमें 'ID' होगा। csvtool namedcol ID csv_file.csv

यह चौथी पंक्ति लौटाएगा: csvtool col 4 csv_file.csv

यदि आप शीर्ष लेख पंक्ति को छोड़ना चाहते हैं:

csvtool col 4 csv_file.csv | sed '1d'


2

मुझे आश्चर्य है कि अब तक के जवाबों में से किसी ने भी csvkit का उल्लेख नहीं किया है।

सीएसवी के साथ कार्य करने और कार्य करने के लिए csvkit कमांड-लाइन टूल का एक सूट है

csvkit प्रलेखन

मैं इसे विशेष रूप से सीएसवी डेटा प्रबंधन के लिए उपयोग करता हूं और अभी तक मुझे ऐसी समस्या नहीं मिली है जिसे मैं cvskit का उपयोग करके हल नहीं कर सका।

Cvs फ़ाइल से एक या अधिक कॉलम निकालने के लिए आप उस csvcutउपयोगिता का उपयोग कर सकते हैं जो टूलबॉक्स का हिस्सा है। दूसरे कॉलम को निकालने के लिए इस कमांड का उपयोग करें:

csvcut -c 2 filename_in.csv > filename_out.csv 

csvcut संदर्भ पृष्ठ

अगर सीएसवी में तार उद्धृत किए जाते हैं, तो qविकल्प के साथ उद्धरण वर्ण जोड़ें :

csvcut -q '"' -c 2 filename_in.csv > filename_out.csv 

के साथ स्थापित करें pip install csvkitया sudo apt install csvkit



0

कुछ समय के लिए इस कोड का उपयोग करते हुए, यह "त्वरित" नहीं है जब तक कि आप "स्टैकओवरफ़्लो से काटने और चिपकाने" की गिनती नहीं करते हैं।

यह IFS के बजाय लूप में $ {##} और $ {%%} ऑपरेटरों का उपयोग करता है। यह 'इरेट' और 'डाई' कहता है, और एसईपी चार्ट के रूप में केवल कॉमा, डैश और पाइप का समर्थन करता है (यह सब मुझे आवश्यक है)।

err()  { echo "${0##*/}: Error:" "$@" >&2; }
die()  { err "$@"; exit 1; }

# Return Nth field in a csv string, fields numbered starting with 1
csv_fldN() { fldN , "$1" "$2"; }

# Return Nth field in string of fields separated
# by SEP, fields numbered starting with 1
fldN() {
        local me="fldN: "
        local sep="$1"
        local fldnum="$2"
        local vals="$3"
        case "$sep" in
                -|,|\|) ;;
                *) die "$me: arg1 sep: unsupported separator '$sep'" ;;
        esac
        case "$fldnum" in
                [0-9]*) [ "$fldnum" -gt 0 ] || { err "$me: arg2 fldnum=$fldnum must be number greater or equal to 0."; return 1; } ;;
                *) { err "$me: arg2 fldnum=$fldnum must be number"; return 1;} ;;
        esac
        [ -z "$vals" ] && err "$me: missing arg2 vals: list of '$sep' separated values" && return 1
        fldnum=$(($fldnum - 1))
        while [ $fldnum -gt 0 ] ; do
                vals="${vals#*$sep}"
                fldnum=$(($fldnum - 1))
        done
        echo ${vals%%$sep*}
}

उदाहरण:

$ CSVLINE="example,fields with whitespace,field3"
$ $ for fno in $(seq 3); do echo field$fno: $(csv_fldN $fno "$CSVLINE");  done
field1: example
field2: fields with whitespace
field3: field3

0

आप लूप करते समय भी उपयोग कर सकते हैं

IFS=,
while read name val; do
        echo "............................"

        echo Name: "$name"
done<itemlst.csv

यह कोड शेलचेक चेतावनी का उत्पादन करता है: SC2034 । इस सवाल को पहले परिणाम के रूप में खोजता है जब चेतावनी को दरकिनार करने के तरीके खोजता है।
jww
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.