web-dev-qa-db-fra.com

Réorganisation de colonnes en utilisant awk

J'essaie de déplacer la 7ème colonne de mon fichier CSV à la fin en utilisant

awk -F '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}',OFS= "$file"

où $ Fichier est un fichier .csv dans un répertoire. Cependant, la sortie est

awk:                          ^ syntax error

Est-ce que quelqu'un sait comment corriger cette erreur?

13
rmb

Les -F L'option nécessite un argument: -F, par exemple.

La fin du script awk doit être séparé avec un (espace de caractères) avec le reste des paramètres.

Si le séparateur de champ est , Et vous souhaitez le garder, et si le nombre de colonnes est constant et inférieur à celui ou égal à 11, essayez de tenter cela:

awk -F, '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}' OFS=, "$file"
11
Jay jargot

Une solution plus courte serait

awk -F',+' -v OFS=, '{$(NF+1)=$7; $7=""; $0=$0; $1=$1}1' file

Je ne sais pas si ,+ Fonctionnera dans toutes les versions awk, mais fonctionne au moins dans GNU awk, également avec -c Ompatiespace mode.

Explication:

  • $(NF+1)=$7: Nous ajoutons d'abord 7ème champ à la fin de la ligne (pourrait être $12=$7 Dans ce cas)
  • $7="": Dans l'étape suivante 7ème champ est effacée (mais les délimiteurs environnants restent)
  • pour supprimer les délimiteurs, nous devons ré-définir un enregistrement entier (via $0=$0) traiter plusieurs virgules comme séparateur de champ (Ceci est effectué via -F',+', ici + signifie un ou plusieurs fois ), et réorganise également l'enregistrement de courant via $1=$1 pour forcer la reconstruction de la ligne à l'aide du séparateur de champ de sortie défini précédemment (défini par une option -v OFS=,)
  • après que tout mélange est fait, nous sommes prêts à imprimer le résultat avec 1

Exemple d'entrée:

1,2,3,4,5,6,7,8,9,10,11

sortir

1,2,3,4,5,6,8,9,10,11,7
8
jimmij

Si vous imprimez avec OFS=, donc sans séparateur entre les champs, vous pouvez simplement enregistrer la valeur de $7 Dans une variable, ensemble $7 Pour vider et imprimer la ligne et la variable directement. Vous n'avez pas besoin de spécifier tous les champs:

$ cat file
1,2,3,4,5,6,7,8
$ awk -F, -vOFS= '{k=$7; $7=""; print $0,k}' file 
12345687
5
terdon

Vous voulez probablement dire:

awk -F, -v OFS='' '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}' "$file"
3
Michael Vehrs

Vous n'avez pas dit spécifiquement que vous vouliez utiliser AWK, et vous DID Disez que vous vouliez utiliser un édition sur place comme prévu par sed -i, alors voici un sed -i une variante. Habituellement awk est préférable de travailler avec des colonnes, mais c'est un cas où je préfère sed, car il gère naturellement un nombre arbitraire de colonnes.

MOVECOL=7
N=$((MOVECOL-1))
sed -r -e "s/^(([^,]*,){$N})([^,]*),(.*)/\1\4,\3/" -i test.csv

Explication:

  • -r Sélectionne des expulsions étendues afin que nous évitons beaucoup de glashes
  • le premier groupe est N $ N répétitions de chaînes terminées par des virgules, autrement dit les colonnes avant celle que nous voulons bouger, avec une virgule finale
  • deuxième groupe est la répétition $ N-ème, nous l'oublions
  • troisième groupe est la colonne que nous voulons bouger, sans la virgule finale
  • quatrième groupe est composé de toutes les colonnes après celle que nous voulons bouger, sans aucune virgule avant
  • nous remplaçons par le premier groupe, le dernier groupe et la colonne que nous avons extraite, insérant la virgule au besoin.

Bien sûr, cela ne fonctionnera pas avec des fichiers qui cachent des virgules dans des devis (ou pire, échappez-leur), mais AWK ne gérera pas cela sans une acrobatie sérieuse. Si vous avez ce problème, vous seriez mieux avec le module PerlText:CSV ou le module pythoncsv.

3
Law29