J'essaie de déplacer la 7e 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ù $ file est un fichier .csv dans un répertoire. Cependant, la sortie est
awk: ^ syntax error
Quelqu'un sait-il comment corriger cette erreur?
^
indique la partie spécifique de la commande où l'erreur a été rencontrée.Réponses:
L'
-F
option a besoin d'un argument:-F,
par exemple.La fin du
awk
script doit être séparée par un(caractère espace) avec le reste des paramètres.
Si le séparateur de champ est
,
et que vous souhaitez le conserver, et si le nombre de colonnes est constant et inférieur ou égal à 11, essayez ceci:la source
command file > newfile && mv newfile file
. Cela dit, la version plus récente de GNUawk
pour soutenir ceci:gawk -i inplace '{blah blah}' file
.mv newfile file
vous pouvez utilisercat newfile > file ; rm -f newfile
- cela préserve l'inode et les autorisations defile
.mktemp
plutôt que de coder en dur les noms de fichiers temporaires dans les scripts. par exempletf=$(mktemp) ; command file > "$tf" ; cat "$tf" > file ; rm -f "$tf"
Une solution plus courte serait
Je ne sais pas si
,+
cela fonctionnera dans toutes lesawk
versions, mais fonctionne au moins dans GNU awk, également avec le-c
mode de compatibilité.Explication:
$(NF+1)=$7
: nous ajoutons d'abord le 7ème champ à la fin de la ligne (pourrait être$12=$7
dans ce cas)$7=""
: à l'étape suivante, le 7ème champ est effacé (mais les délimiteurs environnants restent)$0=$0
) en traitant plusieurs virgules comme séparateur de champ (cela se fait via-F',+'
,+
signifie ici une ou plusieurs fois), et également réorganiser l'enregistrement actuel via$1=$1
pour forcer la reconstruction de la ligne en utilisant le champ de sortie précédemment défini séparateur (défini par une option-v OFS=,
)1
Exemple d'entrée:
production
la source
,+
devrait donc fonctionner.all,ball,call,,,fall
→all,ball,call,fall
). (2)$(NF+1)=$7
est une approche intelligente. À mon humble avis,$0 = $0 OFS $7
est un peu plus clair, seulement quelques caractères de plus, et il semble faire la même chose. Pouvez-vous penser à une situation dans laquelle$0 = $0 OFS $7
ne fait pas la même chose que votre code?$0=$0 OFS $7
est probablement identique à$(NF+1)=$7
, mais uniquement avec le reste du code inchangé, pas en général.Si vous imprimez avec
OFS=
, donc sans séparateur entre les champs, vous pouvez simplement enregistrer la valeur de$7
dans une variable, définie$7
sur vide et imprimer directement la ligne et la variable. Vous n'avez pas besoin de spécifier tous les champs:la source
Vous voulez probablement dire:
la source
awk
ne voit jamais les guillemets simplesOFS=''
, non? Vous pouvez aussi bien taperOFS=
; c'est exactement pareil.Vous n'avez pas dit spécifiquement que vous vouliez utiliser awk, et vous avez dit que vous vouliez utiliser l' édition en place comme prévu par
sed -i
, alors voici unesed -i
variante. Ilawk
est généralement préférable de travailler avec des colonnes, mais c'est un cas où je préfèresed
, car il gère naturellement des nombres arbitraires de colonnes.Explication:
-r
sélectionne des expressions régulières étendues afin d'éviter de nombreuses contre-obliquesBien sûr, cela ne fonctionnera pas avec des fichiers qui cachent des virgules entre guillemets (ou pire, les échappent), mais awk ne s'en occupera pas non plus sans quelques acrobaties sérieuses. Si vous avez ce problème, vous feriez mieux avec le
perl
moduleText:CSV
ou lepython
modulecsv
.la source
Quelques
awk
variantes (en supposant que votre fichier se trouve à l'intérieur de la variable$file
)Ici, vous pouvez faire défiler toutes les colonnes, imprimer avec le séparateur de champ (OFS) et imprimer le terminateur d'enregistrement (ORS) à la fin de la ligne.
Ici avec l'utilisation d'une expression régulière et de la
gensub()
fonctiontuer le 7 e champ et l'imprimer à la fin de la ligne.
$0
est tout le record$n
est le nième recordNF
est le nombre de champs de la ligne couranteOFS
le séparateur déposé en sortieORS
le terminateur d'enregistrement de sortie1
est l'astuce pour dire awktrue
et imprimer la valeur par défaut ($0
).Mettre à jour ...
J'oublie presque, il est possible de décaler toutes les colonnes après la 7 ème .
la source
OFS $7
serait plus robuste que"," $7
. (2) Je pense que", " $7
c'est faux, dans la mesure où la question indique que l'OP ne veut pas d'espaces après les virgules. (Et, si les données d'entrée avaient des espaces après les virgules, alors$7
commenceraient déjà par un espace, et vous en ajouteriez un supplémentaire.)OFS $7
, non seulement plus robuste, mais encore plus général ( "la hâte fait gaspiller" )