Désolé si c'est trop basique. J'ai un fichier CSV où les colonnes ont une ligne d'en-tête (v1, v2, etc.). Je comprends que pour extraire les colonnes 1 et 2, je dois faire: awk -F "," '{print $1 "," $2}' infile.csv > outfile.csv
. Mais que se passe-t-il si je dois extraire, par exemple, les colonnes 1 à 10, 20 à 25 et 30, 33? En tant qu'additif, existe-t-il un moyen d'extraire directement avec les noms d'en-tête plutôt qu'avec les numéros de colonne?
Je ne sais pas s'il est possible de faire des gammes dans awk. Vous pouvez faire une boucle for, mais vous devez ajouter un traitement pour filtrer les colonnes que vous ne voulez pas. C'est probablement plus facile à faire:
awk -F, '{OFS=",";print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$20,$21,$22,$23,$24,$25,$30,$33}' infile.csv > outfile.csv
autre chose à considérer - et ceci plus rapide et plus concis:
cut -d "," -f1-10,20-25,30-33 infile.csv > outfile.csv
En ce qui concerne la deuxième partie de votre question, j'écrirais probablement un script en Perl qui sait comment gérer les lignes d'en-tête, en analysant les noms de colonnes de stdin ou d'un fichier, puis en effectuant le filtrage. C'est probablement un outil que je voudrais avoir pour d'autres choses. Je ne suis pas sûr de pouvoir faire un aller simple, même si je suis sûr que cela peut être fait.
Comme mentionné par @Tom, les approches cut et awk ne fonctionnent pas pour les CSV contenant des chaînes entre guillemets. Une alternative est un module pour python qui fournit l'outil de ligne de commande csvfilter. Cela fonctionne comme couper, mais gère correctement les colonnes CSV citant:
csvfilter -f 1,3,5 in.csv > out.csv
Si vous avez Python (et vous devriez le faire), vous pouvez l'installer simplement comme ceci:
pip install csvfilter
Veuillez noter que l'indexation des colonnes dans csvfilter commence par 0 (contrairement à awk, qui commence par $ 1). Plus d'infos sur https://github.com/codeinthehole/csvfilter/
D'autres ont répondu à votre question précédente. Pour ça:
En tant qu'additif, existe-t-il un moyen d'extraire directement avec les noms d'en-tête plutôt qu'avec les numéros de colonne?
Je ne l'ai pas essayé, mais vous pouvez stocker l'index de chaque en-tête dans un hachage, puis utiliser ce hachage pour obtenir son index ultérieurement.
for(i=0;i<$NF;i++){
hash[$i] = i;
}
Puis plus tard, utilisez-le:
j = hash["header1"];
print $j;
D'autres langues ont des raccourcis pour les plages de numéros de champs, mais pas awk, vous devrez écrire votre code comme peur
awk -F, 'BEGIN {OFS=","} { print $1, $2, $3, $4 ..... $30, $33}' infile.csv > outfile.csv
Awk n'a pas pour fonction directe d'utiliser les noms de champs comme spécificateurs de colonnes.
J'espère que ça aide.
Vous pouvez utiliser une boucle for pour adresser un champ avec $ i :
ls -l | awk '{for(i=3 ; i<8 ; i++) {printf("%s\t", $i)} print ""}'
Tabulator est un ensemble d’outils de ligne de commande unix permettant de travailler avec des fichiers CSV comportant des lignes d’en-tête. Voici un exemple pour extraire des colonnes par nom à partir d'un fichier test.csv:
name,sex,house_nr,height,shoe_size
arthur,m,42,181,11.5
berta,f,101,163,8.5
chris,m,1333,175,10
don,m,77,185,12.5
elisa,f,204,166,7
Alors tblmap -k name,height test.csv
produit
name,height
arthur,181
berta,163
chris,175
don,185
elisa,166
Ne pas utiliser awk mais le moyen le plus simple de le faire était d’utiliser simplement csvtool . J'avais également d'autres cas d'utilisation pour utiliser csvtool, qui peut gérer les guillemets ou les délimiteurs de manière appropriée s'ils apparaissent dans les données de colonne elles-mêmes.
csvtool format '%(2)\n' input.csv
csvtool format '%(2),%(3),%(4)\n' input.csv
Si vous remplacez 2 par le numéro de colonne, les données de colonne recherchées seront extraites.