Comment imprimer la troisième colonne à la dernière colonne?


121

J'essaie de supprimer les deux premières colonnes (qui ne m'intéressent pas) d'un fichier journal DbgView. Je n'arrive pas à trouver un exemple qui imprime à partir de la colonne 3 jusqu'à la fin de la ligne. Notez que chaque ligne a un nombre variable de colonnes.


Réponses:


108

... ou une solution plus simple: cut -f 3- INPUTFILE ajoutez simplement le séparateur correct (-d) et vous obtenez le même effet.


9
Notez que cela ne fonctionne que si le délimiteur est exactement le même entre toutes les colonnes ... Par exemple, vous ne pouvez pas utiliser couper avec un délimiteur comme \ d +. (À ma connaissance.)
Zach Wily

72
Lorsque la question est intitulée awk, il est inapproprié d'accepter une réponse autre que awk. Et si les gens en avaient besoin pour les scripts awk? Cette réponse aurait dû être juste un commentaire.
syaz

24
@SyaZ: Normalement, je suis d'accord, mais avec la quantité de «awk gratuit» qui se passe sur ce tableau, j'ai pensé qu'il était nécessaire de montrer une autre façon de faire la tâche. Ne seriez-vous pas reconnaissant si quelqu'un vous montrait un moyen plus simple et plus rapide de faire la même tâche? Peut-être que l'affiche a pensé que awk est le seul moyen de le faire en raison du nombre de réponses `` non incorrectes, mais certainement améliorables '' à d'autres questions?
Marcin

12
C'est à cela que sert le commentaire. Acceptez la meilleure réponse awk et fournissez de meilleures suggestions non-awk sur les commentaires. Si les gens commencent à publier des réponses qui ne répondent pas exactement aux questions, ce sera ennuyeux lors de la recherche (dans mon cas).
syaz

12
Non seulement le délimiteur doit être le même entre toutes les colonnes, mais il doit y avoir EXACTEMENT UN caractère de délimitation entre les colonnes. Donc, si vous avez affaire à des programmes qui alignent leur sortie avec des délimiteurs, il est préférable d'utiliser awk.
sknaumov

112
awk '{for(i=3;i<=NF;++i)print $i}' 

3
awk '{for (i = 3; i <= NF; ++ i) print $ i}' soit plus compact. :)
user172818

1
Merci, lh3. J'étais juste en train de copier et coller pour le manuel de gawk. :)
Jonathan Feinberg

23
cela échoue avec plusieurs lignes, chaque colonne est traitée comme une nouvelle ligne lors de l'impression iwth print
meso_2600

13
Pour résoudre le problème de sortie fractionnée, je propose cette solution: awk '{for(i=3;i<=NF;++i)printf $i""FS ; print ""}'( printfn'imprimera pas le caractère de nouvelle ligne alors que print ""j'ajouterai une nouvelle ligne après que les autres champs aient été imprimés)
lauhub

1
Ou: echo $(seq 1 10) | awk '{for (i=3; i<=NF; i++) printf $i FS}', ce qui donne: 3 4 5 6 7 8 9 10.
x-yuri

106

23
Je suis un peu en retard pour cela, mais cela ne fonctionnera pas pour les enregistrements dans lesquels le premier ou le deuxième champ est égal au troisième (par exemple, 3 2 3 4 5)
aleph_null

l'impression d'une plage interne est également possible: `` `` # de 3 $ (inclus) à 6 $ (exclus); echo "1,2,3,4,5,6,7,8,9" | awk 'BEGIN {FS = ","; OFS = ","} {print substr ($ 0, index ($ 0, $ 3), length ($ 0) -index ($ 0, $ 6) -1)}'; # donne 3,4,5 ''
splaisan

34

La réponse de Jonathan Feinberg imprime chaque champ sur une ligne distincte. Vous pouvez utiliser printfpour reconstruire l'enregistrement pour une sortie sur la même ligne, mais vous pouvez également simplement déplacer les champs d'un saut vers la gauche.

awk '{for (i=1; i<=NF-2; i++) $i = $(i+2); NF-=2; print}' logfile

1
Sachez que cela ne fonctionne que pour Gnu awk, la décrémentation NFn'est pas autorisée par POSIX.
kvantour le

1
@kvantour: Cela fonctionne sous gawk, mawk, MacOS awk (nawk?). POSIX semble être silencieux sur la possibilité de NFdécrémenter.
Suspendu jusqu'à nouvel ordre.

C'est l'un de ces drôles de coins sombres de awk .
kvantour le

19
awk '{$1=$2=$3=""}1' file

NB: cette méthode laissera des "blancs" dans les champs 1,2,3 mais pas de problème si vous voulez juste regarder la sortie.


Suivez cette commande avec `| sed s / ^ \ * // | column -t` pour supprimer les espaces de début et aligner les colonnes restantes
MSpreij

Que signifie le dernier 1? avec quel mot clé dois-je rechercher awk?
Itachi


1
@Nathan vous résolvez ce problème en tant que{$1=$2=$3="";$0=$0;$1=$1}1
kvantour

11

Si vous souhaitez imprimer les colonnes après le 3 par exemple dans la même ligne, vous pouvez utiliser:

awk '{for(i=3; i<=NF; ++i) printf "%s ", $i; print ""}'

Par exemple:

Mar 09:39 20180301_123131.jpg
Mar 13:28 20180301_124304.jpg
Mar 13:35 20180301_124358.jpg
Feb 09:45 Cisco_WebEx_Add-On.dmg
Feb 12:49 Docker.dmg
Feb 09:04 Grammarly.dmg
Feb 09:20 Payslip 10459 %2828-02-2018%29.pdf

Il imprimera:

20180301_123131.jpg
20180301_124304.jpg
20180301_124358.jpg
Cisco_WebEx_Add-On.dmg
Docker.dmg
Grammarly.dmg
Payslip 10459 %2828-02-2018%29.pdf

Comme nous pouvons le voir, la fiche de paie, même avec un espace, apparaît dans la ligne correcte.


Rapide et élégant. Merci;)
9nz9

C'est excellent, sauf que j'ai un problème avec l'exclusion de $ NF. Lorsque je règle la condition (<= NF), j'obtiens le dernier champ mais le premier caractère du premier champ est coupé. Suis-je mal compris quelque chose en termes de fonctionnalité?
Ken Ingram le

On dirait que mon problème est que ^ M est bloqué à la fin de la dernière colonne. Je ne vois pas comment le supprimer.
Ken Ingram le

8

Qu'en est-il de la ligne suivante:

awk '{$ 1 = $ 2 = $ 3 = ""; imprimer le fichier

Basé sur la suggestion de @ ghostdog74. Le mien devrait mieux se comporter lorsque vous filtrez les lignes, c'est-à-dire:

awk '/ ^ exim4-config / {$ 1 = ""; imprimer le fichier

Court et simple. Pourrait également ajouter et ajouter sed 's/\s\+//g'à la fin de la commande pour couper les espaces de
début

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

Cela coupe ce qui se trouve avant le champ nr., N et imprime tout le reste de la ligne, y compris le champ nrN et en conservant l'espacement d'origine (il ne reformate pas). Cela n'a pas d'importance si la chaîne du champ apparaît également ailleurs dans la ligne, ce qui est le problème avec la réponse de daisaa.

Définissez une fonction:

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

Et utilisez-le comme ceci:

$ 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

Fonctionne bien pour les fichiers où «/ n» est le séparateur d'enregistrement afin que vous n'ayez pas ce caractère de nouvelle ligne à l'intérieur des lignes. Si vous souhaitez l'utiliser avec d'autres séparateurs d'enregistrement, utilisez:

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

par exemple. Fonctionne bien avec presque tous les fichiers tant qu'ils n'utilisent pas de caractères hexadécimaux. 1 à l'intérieur des lignes.


4

La commande awk suivante imprime les N derniers champs de chaque ligne et à la fin de la ligne imprime un nouveau caractère de ligne:

awk '{for( i=6; i<=NF; i++ ){printf( "%s ", $i )}; printf( "\n"); }'

Trouvez ci-dessous un exemple qui répertorie le contenu du répertoire / usr / bin, puis contient les 3 dernières lignes, puis imprime les 4 dernières colonnes de chaque ligne en utilisant awk:

$ ls -ltr /usr/bin/ | tail -3
-rwxr-xr-x 1 root root       14736 Jan 14  2014 bcomps
-rwxr-xr-x 1 root root       10480 Jan 14  2014 acyclic
-rwxr-xr-x 1 root root    35868448 May 22  2014 skype

$ ls -ltr /usr/bin/ | tail -3 | awk '{for( i=6; i<=NF; i++ ){printf( "%s ", $i )}; printf( "\n"); }'
Jan 14 2014 bcomps 
Jan 14 2014 acyclic 
May 22 2014 skype

4
awk '{a=match($0, $3); print substr($0,a)}'

Vous trouvez d'abord la position du début de la troisième colonne. Avec substr, vous imprimerez la ligne entière ($ 0) en commençant à la position (dans ce cas a) jusqu'à la fin de la ligne.


3

Eh bien, vous pouvez facilement obtenir le même effet en utilisant une expression régulière. En supposant que le séparateur est un espace, cela ressemblerait à:

awk '{ sub(/[^ ]+ +[^ ]+ +/, ""); print }'

1
J'éviterais les regex. Il est probablement plus lent et plus facile de gâcher accidentellement.
Cascabel

1
Il le raccourcit comme ceci: ce awk '{ sub(/([^ ]+ +){2}/, ""); print }'qui enlève le motif deux fois.
erik le


2

Solution Perl:

perl -lane 'splice @F,0,2; print join " ",@F' file

Ces options de ligne de commande sont utilisées:

  • -n boucle autour de chaque ligne du fichier d'entrée, n'imprime pas automatiquement chaque ligne

  • -l supprime les nouvelles lignes avant le traitement et les rajoute par la suite

  • -amode autosplit - divise les lignes d'entrée dans le tableau @F. Par défaut, diviser sur les espaces

  • -e exécuter le code perl

splice @F,0,2 supprime proprement les colonnes 0 et 1 du tableau @F

join " ",@F joint les éléments du tableau @F, en utilisant un espace entre chaque élément

Si votre fichier d'entrée est délimité par des virgules, plutôt que par des espaces, utilisez -F, -lane


Solution Python:

python -c "import sys;[sys.stdout.write(' '.join(line.split()[2:]) + '\n') for line in sys.stdin]" < file


1

Un peu tard ici, mais rien de ce qui précède ne semblait fonctionner. Essayez ceci, en utilisant printf, insère des espaces entre chacun. J'ai choisi de ne pas avoir de nouvelle ligne à la fin.

awk '{for(i=3;i<=NF;++i) printf("%s ",  $i) }'

1
awk '{for (i=4; i<=NF; i++)printf("%c", $i); printf("\n");}'

imprime les enregistrements commençant du 4e champ au dernier champ dans le même ordre qu'ils étaient dans le fichier d'origine


désolé, ce n'était pas une réponse tout à fait correcte. c'est trop précis, mais je ne sais pas comment le supprimer
Massimo


0

S'il ne s'agit que d'ignorer les deux premiers champs et si vous ne voulez pas d'espace pour masquer ces champs (comme le font certaines des réponses ci-dessus):

awk '{gsub($1" "$2" ",""); print;}' file

0
awk '{$1=$2=""}1' FILENAME | sed 's/\s\+//g'

Les deux premières colonnes sont effacées, sedsupprime les espaces de début.


-2

Dans AWK, les colonnes sont appelées champs, donc NF est la clé

toutes les lignes:

awk -F '<column separator>' '{print $(NF-2)}' <filename>

première ligne uniquement:

awk -F '<column separator>' 'NR<=1{print $(NF-2)}' <filename>
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.