99 votes

Comment imprimer toutes les colonnes après un nombre particulier en utilisant awk ?

Sur l'interpréteur de commandes, je pipe vers awk lorsque j'ai besoin d'une colonne particulière.

Cela permet d'imprimer la colonne 9, par exemple :

... | awk '{print $9}'

Comment puis-je demander à awk d'imprimer toutes les colonnes ? y compris et après la colonne 9 et pas seulement la colonne 9 ?

95voto

Amadan Points 41944
awk '{ s = ""; for (i = 9; i <= NF; i++) s = s $i " "; print s }'

4 votes

Quelques légères améliorations : awk -v N=9 '{sep=""; for (i=N; i<=NF; i++) {printf("%s%s",sep,$i); sep=OFS}; printf("\n")}'

0 votes

Merci @glenn, c'est en effet un peu plus général. Quoi qu'il en soit, je suis tout à fait d'accord pour dire qu'il serait préférable d'utiliser cut o perl pour cela. N'utilisez cette option que si vous tenez vraiment à l'avoir dans vos dossiers. awk .

0 votes

Quelques améliorations supplémentaires : awk -v N=9 '{for(i=1;i<N;i++){$i=""}}1' Bien qu'il ajoute quelques octets NUL à l'avant.

74voto

SiegeX Points 32614

Lorsque vous voulez faire une gamme de champs, awk n'a pas vraiment de moyen direct de le faire. Je recommande cut à la place :

cut -d' ' -f 9- ./infile

Editar

Ajout d'un délimiteur de champ de type espace, la valeur par défaut étant une tabulation. Merci à Glenn de l'avoir signalé

15 votes

Une chose à propos de cut est qu'il utilise un délimiteur spécifique (tabulation par défaut), là où awk utilise "l'espace blanc". Avec cut, 2 tabulations consécutives délimitent un champ vide.

1 votes

Comme @glennjackman l'a souligné, le délimiteur d'awk est "l'espace blanc" (n'importe quelle quantité, aussi). Donc, définir le délimiteur de coupe à un seul espace ne correspondrait pas non plus au comportement. Malheureusement, la boucle est le mieux que l'on puisse faire, donc il semble.

0 votes

Celui-ci ne fonctionne pas correctement. Essayez la commande find . | xargs ls -l | cut -d' ' -f 9- . Pour une raison quelconque, les doubles espaces sont également comptés. Exemple : lrwxrwxrwx 1 me me 21 Dec 12 00:00 ./file_a lrwxrwxrwx 1 me me 64 Dec 6 00:06 ./file_b aura pour résultat ./file_a 00:06 ./file_b

55voto

Ascherer Points 3645
awk '{print substr($0, index($0,$9))}'

Editar : Remarque, cela ne fonctionne pas si un champ avant le neuvième contient la même valeur que le neuvième.

10 votes

@veryhungrymike : ...et ne fonctionne pas si un champ avant le neuvième contient la même valeur que le neuvième.

0 votes

C'est vrai, mais j'espère que votre fichier n'a pas ce problème ! Ce n'est pas la seule ni la meilleure solution pour le PO, mais cela peut fonctionner.

6 votes

Probablement à cause de la phrase classique "espérons que votre fichier ne présente pas ce problème". C'est un total no-no en ingénierie s/w à l'état : "Nous n'allons pas perdre de temps à inclure un contrôle d'erreur pour l'entrée de valeurs négatives, par exemple, parce que nous espérons que l'utilisateur sera suffisamment intelligent pour ne pas les essayer et faire planter notre outil. HAHAHA ! J'aime toujours entendre ça ! (J'aime un bon sens de l'humour) Eh bien, comme des idiots faire existent, c'est le devoir du développeur de faire en sorte que son matériel à l'abri des regards ! Au lieu d'"espérer le bien de l'homme". C'est plutôt une attitude que l'on attend des philosophes, pas des ingénieurs s/w...LOL

11voto

bobbogo Points 4201

En général, perl remplace awk/sed/grep et autres, et est beaucoup plus portable (ainsi qu'un meilleur canif).

perl -lane 'print "@F[8..$#F]"'

Timtowtdi s'applique bien sûr.

0 votes

Vous devez ajouter l'option de ligne de commande -l ou ajouter \n à l'instruction d'impression.

0 votes

@glenn jackman : Possible. Non requis s'il fait partie d'un autre message, ou s'il est assigné à une variable, etc. En ce qui concerne le "mieux", perl est certainement plus beau dans les petites structures. Il est vrai qu'il peut paraître très désordonné dans les grandes structures.

0 votes

Ne vous méprenez pas, j'aime Perl. Mais j'aime l'awk pour ce qu'il est.

5voto

Robert Vila Points 61
awk -v m="\x01" -v N="3" '{$N=m$N ;print substr($0, index($0,m)+1)}'

Cette commande coupe ce qui se trouve avant le champ nr. donné, N, et imprime tout le reste de la ligne, y compris le champ nr.N et en maintenant l'espacement original (elle ne reformate pas). Cela n'a pas d'importance si la chaîne du champ apparaît aussi quelque part ailleurs dans la ligne, ce qui est le problème avec la réponse d'Ascherer.

Définir une fonction :

fromField () { 
awk -v m="\x01" -v N="$1" '{$N=m$N; print substr($0,index($0,m)+1)}'
}

Et utilise-le comme ça :

$ echo "  bat   bi       iru   lau bost   " | fromField 3
iru   lau bost   
$ echo "  bat   bi       iru   lau bost   " | fromField 2
bi       iru   lau bost   

La sortie conserve tout, y compris les espaces de fin de ligne Pour N=0, il renvoie la ligne entière, telle quelle, et pour n>NF, la chaîne vide.

0 votes

C'est une bonne idée. Cela ne fonctionne pas tout à fait sur un Mac actuel utilisant gawk typique, parce que $0 s'effondre. La solution consiste à définir une variable à 0 $ en tant que première étape, comme : '{s=$0 ; ... print substr(s,index(s,m)+1}

0 votes

Cela va certainement reformater la ligne puisque $N=m$N c'est le changement de la valeur d'un champ qui provoque la reconstruction d'awk $0 en remplaçant tous les FS par des OFS. Je ne peux pas imaginer comment vous obtenez la sortie que vous montrez étant donné ce script.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X