Si j'ai un fichier csv, existe-t-il un moyen rapide en bash d'imprimer le contenu d'une seule colonne ? On peut supposer en toute sécurité que chaque ligne a le même nombre de colonnes, mais le contenu de chaque colonne aurait une longueur différente.
Réponses
Trop de publicités?Voici un exemple de fichier CSV avec 2 colonnes
myTooth.csv
Date,Tooth
2017-01-25,sagesse
2017-02-19,canine
2017-02-24,canine
2017-02-28,sagesse
Pour obtenir la première colonne, utilisez:
cut -d, -f1 myTooth.csv
f représente le champ et d représente le délimiteur
En exécutant la commande ci-dessus, vous obtiendrez la sortie suivante.
Sortie
Date
2017-01-25
2017-02-19
2017-02-24
2017-02-28
Pour obtenir uniquement la 2ème colonne :
cut -d, -f2 myTooth.csv
Et voici la sortie Sortie
Tooth
sagesse
canine
canine
sagesse
incisive
Un autre cas d'utilisation:
Votre fichier d'entrée CSV contient 10 colonnes et vous souhaitez les colonnes 2 à 5 et 8, en utilisant la virgule comme séparateur".
cut utilise -f (signifiant "champs") pour spécifier les colonnes et -d (signifiant "délimiteur") pour spécifier le séparateur. Vous devez spécifier ce dernier car certains fichiers peuvent utiliser des espaces, des tabulations ou des deux-points pour séparer les colonnes.
cut -f 2-5,8 -d , myvalues.csv
cut est une utilitaire de commande et voici quelques exemples supplémentaires:
SYNOPSIS
cut -b liste [-n] [fichier ...]
cut -c liste [fichier ...]
cut -f liste [-d delim] [-s] [fichier ...]
De nombreuses réponses à cette question sont excellentes et certaines ont même examiné les cas particuliers. J'aimerais ajouter une réponse simple qui peut être utile au quotidien... là où vous rencontrez le plus souvent ces cas particuliers (comme des virgules échappées ou des virgules entre guillemets, etc.,).
FS (Field Separator) est la variable dont la valeur est par défaut définie sur un espace. Ainsi, awk divise par défaut à l'espace pour n'importe quelle ligne.
En utilisant BEGIN (Exécuter avant de prendre l'entrée) nous pouvons définir ce champ à n'importe quoi que nous voulons...
awk 'BEGIN {FS = ","}; {print $3}'
Le code ci-dessus affichera la 3ème colonne dans un fichier csv.
Les autres réponses fonctionnent bien, mais puisque vous avez demandé une solution utilisant uniquement le shell bash, vous pouvez faire ceci :
AirBoxOmega:~ d$ cat > file #Tout d'abord, nous allons créer un CSV de base
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
Ensuite, vous pouvez extraire des colonnes (la première dans cet exemple) de cette manière :
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
Il se passe donc quelques choses ici :
-
while IFS=,
- cela signifie d'utiliser une virgule comme le séparateur interne de champs (IFS), c'est 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 "a b" si l'IFS=" " (ce qui est le cas par défaut). -
read -a csv_line;
- cela signifie de lire chaque ligne, une par une, et de créer un tableau où chaque élément est appelé "csv_line" et l'envoyer à la section "do" de notre boucle while. -
do echo "${csv_line[0]}";done < file
- maintenant nous sommes dans la phase "do", et nous disons d'afficher le 0ème élément du tableau "csv_line". Cette action est répétée sur chaque ligne du fichier. La partie< file
indique simplement à la boucle while où lire. REMARQUE : n'oubliez pas, en bash, les tableaux sont indexés à partir de 0, donc la première colonne est le 0ème élément.
Voilà, vous avez donc extrait une colonne d'un CSV dans le shell. Les autres solutions sont probablement plus pratiques, mais celle-ci est purement en bash.