Comment extraire une colonne d’un fichier csv

Si j’ai un fichier csv, existe-t-il un moyen rapide d’imprimer le contenu d’une seule colonne? Il est prudent de supposer que chaque ligne a le même nombre de colonnes, mais le contenu de chaque colonne aura une longueur différente.

    Vous pouvez utiliser awk pour cela. Remplacez «$ 2» par la colonne que vous souhaitez.

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

    Oui. cat mycsv.csv | cut -d ',' -f3 cat mycsv.csv | cut -d ',' -f3 imprimera la 3ème colonne.

    La façon la plus simple de faire cela était d’utiliser csvtool . J’ai également eu d’autres cas d’utilisation pour utiliser csvtool et il peut gérer les guillemets ou les délimiteurs de manière appropriée s’ils apparaissent dans les données de la colonne elle-même.

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

    Remplacer 2 par le numéro de colonne extraira efficacement les données de colonne que vous recherchez.

    Atterri ici pour extraire un fichier séparé par des tabulations. Je pensais append.

     cat textfile.tsv | cut -f2 -s 

    -f2 extrait la colonne indexée 2, non nulle ou la seconde colonne.

    Les autres réponses fonctionnent bien, mais puisque vous avez demandé une solution en utilisant simplement le shell bash, vous pouvez le faire:

     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 

    Et puis, vous pouvez extraire des colonnes (la première dans cet exemple) comme ceci:

     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 

    Donc, il y a plusieurs choses ici:

    • while IFS=, - cela dit utiliser une virgule comme IFS (Internal Field Separator), ce que le shell utilise pour savoir ce qui sépare les champs (blocs de texte). Donc, dire IFS =, c'est comme dire "a, b" est la même chose que "ab" si IFS = "" (qui est ce que c'est par défaut).

    • read -a csv_line; - ceci dit lire dans chaque ligne, un à la fois et créer un tableau où chaque élément s'appelle "csv_line" et l'envoyer à la section "do" de notre boucle while

    • do echo "${csv_line[0]}";done < file - maintenant nous sums dans la phase "do", et nous disons echo le 0ème élément du tableau "csv_line". Cette action est répétée sur chaque ligne du fichier. La partie < file est juste en train de lire la boucle while. NOTE: rappelez-vous, en bash, les tableaux sont indexés sur 0, donc la première colonne est le 0ème élément.

    Alors voilà, en retirant une colonne d'un CSV dans le shell. Les autres solutions sont probablement plus pratiques, mais celle-ci est pure bash.

    Beaucoup de réponses à ces questions sont excellentes et certaines ont même examiné les cas les plus difficiles. Je voudrais append une réponse simple qui peut être d’utilisation quotidienne … où vous vous retrouvez surtout dans ces cas-types (comme avoir échappé des virgules ou des virgules entre guillemets, etc.).

    FS (Field Separator) est la variable dont la valeur est bloquée dans l’espace. Donc, awk par défaut se divise à l’espace pour n’importe quelle ligne.

    Donc, en utilisant BEGIN (Execute avant de prendre entrée), nous pouvons définir ce champ sur tout ce que nous voulons …

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

    Le code ci-dessus imprimera la 3ème colonne dans un fichier csv.

    [dumb @ one pts] $ cat> file #First nous allons créer un fichier CSV de base
    a, b, c, d, e, f, g, h, i
    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

    [dumb @ one pts] $ awk -F, fichier ‘{print $ 1}’
    une
    1
    une
    1

    Vous pouvez utiliser GNU Awk, voir cet article du guide de l’utilisateur . En guise d’amélioration de la solution présentée dans l’article (en juin 2015), la commande gawk suivante autorise les doubles guillemets dans les champs entre guillemets doubles; une double citation est marquée par deux doubles guillemets consécutifs (“”). De plus, cela permet des champs vides, mais même cela ne peut pas gérer les champs multilignes . L’exemple suivant imprime la 3ème colonne (via c=3 ) de textfile.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  

    Notez l'utilisation de dos2unix pour convertir les éventuels sauts de ligne de style DOS (CRLF, c'est-à-dire "\ r \ n") et le codage UTF-16 (avec marque d'ordre des octets) en "\ n" et UTF-8 (sans marque d'octet), respectivement. . Les fichiers CSV standard utilisent CRLF comme saut de ligne, voir Wikipedia .

    Si l'entrée peut contenir des champs multilignes, vous pouvez utiliser le script suivant. Notez l'utilisation d'une chaîne spéciale pour séparer les enregistrements dans la sortie (puisque la ligne de séparation par défaut du séparateur peut apparaître dans un enregistrement). Encore une fois, l'exemple suivant imprime la 3ème colonne (via c=3 ) de textfile.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  

    Il y a une autre approche du problème. csvquote peut générer le contenu d'un fichier CSV modifié afin que les caractères spéciaux dans le champ soient transformés afin que les outils de traitement de texte Unix habituels puissent être utilisés pour sélectionner certaines colonnes. Par exemple, le code suivant affiche la troisième colonne:

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

    csvquote peut être utilisé pour traiter des fichiers volumineux arbitraires.

    J’avais besoin d’une parsing correcte du CSV, pas de cut / awk et de prière. J’essaie ceci sur un mac sans csvtool , mais les macs viennent avec ruby, donc vous pouvez faire:

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

    Vous ne pouvez pas le faire sans un parsingur CSV complet.

    Vous utilisez ce code depuis un certain temps, il n’est pas “rapide” à moins que vous ne comptiez “couper et coller à partir de stackoverflow”.

    Il utilise les opérateurs $ {##} et $ {%%} dans une boucle au lieu de IFS. Il appelle «err» et «die», et ne supporte que les virgules, les tirets et les tubes comme caractères SEP (c’est tout ce dont j’avais besoin).

     err() { echo "${0##*/}: Error:" "$@" >&2; } die() { err "$@"; exit 1; } # Return Nth field in a csv ssortingng, fields numbered starting with 1 csv_fldN() { fldN , "$1" "$2"; } # Return Nth field in ssortingng 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*} } 

    Exemple:

     $ 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 
     csvtool col 2 file.csv 

    où 2 est la colonne qui vous intéresse

    vous pouvez aussi faire

     csvtool col 1,2 file.csv 

    faire plusieurs colonnes