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?Je me demande pourquoi aucun des réponses jusqu'à présent n'a mentionné csvkit.
csvkit est une suite d'outils en ligne de commande pour convertir et travailler avec des fichiers CSV
Je l'utilise exclusivement pour la gestion des données csv et jusqu'à présent je n'ai pas trouvé de problème que je ne pouvais pas résoudre en utilisant cvskit.
Pour extraire une ou plusieurs colonnes d'un fichier cvs, vous pouvez utiliser l'utilitaire csvcut
qui fait partie de la boîte à outils. Pour extraire la deuxième colonne, utilisez cette commande :
csvcut -c 2 nom_fichier_in.csv > nom_fichier_out.csv
Si les chaînes de caractères dans le csv sont entre guillemets, ajoutez le caractère de guillemet avec l'option q
:
csvcut -q '"' -c 2 nom_fichier_in.csv > nom_fichier_out.csv
Installez avec pip install csvkit
ou sudo apt install csvkit
.
Vous pourriez utiliser GNU Awk, voir cet article du guide de l'utilisateur. Comme amélioration à la solution présentée dans l'article (en juin 2015), la commande gawk suivante permet les guillemets doubles à l'intérieur de champs entre guillemets doubles ; un guillemet double est marqué par deux guillemets doubles consécutifs ("") là-bas. 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
) du fichier texte.csv :
#!/bin/bash
gawk -- '
BEGIN{
FPAT="([^,\"]*)|(\"((\"\")*[^\"]*)*\")"
}
{
if (substr($c, 1, 1) == "\"") {
$c = substr($c, 2, length($c) - 2) # Obtient le texte entre les deux guillemets
gsub("\"\"", "\"", $c) # Normalise les guillemets doubles
}
print $c
}
' c=3 < <(dos2unix
Remarquez l'utilisation de `dos2unix` pour convertir les sauts de ligne de style DOS possibles (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'ordre des octets), respectivement. Les fichiers CSV standard utilisent CRLF comme saut de ligne, voir [Wikipedia](https://en.wikipedia.org/wiki/Comma-separated_values#Standardization).
**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 en sortie (puisque le séparateur de ligne par défaut pourrait être présent dans un enregistrement). Encore une fois, l'exemple suivant imprime la 3ème colonne (via `c=3`) du fichier texte.csv :
#!/bin/bash
gawk -- '
BEGIN{
RS="\0" # Lire le fichier d'entrée complet comme un enregistrement ;
# supposer qu'il n'y a pas de caractère nul dans l'entrée.
FS="" # Supposons que ce paramètre facilite le travail de division interne.
ORS="\n####\n" # Utiliser un séparateur de sortie spécial pour montrer les bordures d'un enregistrement.
}
{
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) # Obtient le texte dans
# les deux guillemets.
gsub(/""/, "\"", a[i]) # Normalise les guillemets doubles.
}
print a[i]
}
if (seps[i]!=",") field=0
}
}
' c=3 < <(dos2unix
``
Il existe une autre approche au problème. [csvquote](https://github.com/dbro/csvquote) peut produire le contenu d'un fichier CSV modifié pour que les caractères spéciaux dans les champs soient transformés de telle sorte que les outils de traitement du 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 de taille arbitraire.
`` ```
Simple solution using awk. Instead of "colNum" put the number of column you need to print.
cat fileName.csv | awk -F ";" '{ print $colNum }'
Traduction en français :
Simple solution using awk. Instead of "colNum" put the number of column you need to print.
cat fileName.csv | awk -F ";" '{ print $colNum }'
Si vous savez que vos données ne seront pas entre guillemets, alors toute solution qui se divise sur ,
fonctionnera bien (j'ai tendance à utiliser cut -d, -f1 | sed 1d
), tout comme n'importe quel outil de manipulation de CSV.
Si vous voulez produire un autre fichier CSV, alors xsv
, csvkit
, csvtool
, ou d'autres outils de manipulation de CSV sont appropriés.
Si vous voulez extraire le contenu d'une seule colonne d'un fichier CSV, désabonnement afin qu'ils puissent être traités par des commandes ultérieures, cette ligne Python fait l'affaire pour les fichiers CSV avec des en-têtes:
python -c 'import csv,sys'$'\n''for row in csv.DictReader(sys.stdin): print(row["message"])'
Le "message"
à l'intérieur de la fonction print
sélectionne la colonne.
Si le fichier CSV n'a pas d'en-têtes:
python -c 'import csv,sys'$'\n''for row in csv.reader(sys.stdin): print(row[1])'
La bibliothèque CSV de Python prend en charge toutes sortes de dialectes CSV, donc si votre fichier CSV utilise des conventions différentes, il est possible de les prendre en charge avec relativement peu de modifications dans le code.