Imprimer l'avant-dernière colonne / champ dans awk

165

Je veux imprimer l'avant-dernière colonne ou champ dans awk. Le nombre de champs est variable. Je sais que je devrais pouvoir utiliser $NFmais je ne sais pas comment il peut être utilisé.

Et cela ne semble pas fonctionner:

awk ' { print ( $NF-- )  } '
Brian G
la source
10
NFest le dernier index de champ, $NFest la valeur du dernier champ
glenn jackman
cela a du sens maintenant. c'est pourquoi le dollar en dehors de la parenthèse fonctionne, je suppose
Brian G

Réponses:

280
awk '{print $(NF-1)}'

Devrait marcher

Chris Kannon
la source
2
Cela ne fonctionne pas pour moi. J'obtiens "title: 5: command not found: NF-1" dans awk 3.1.8 sous Ubuntu.
Gurgeh
3
J'éviterais la décrémentation pré / post pour m'assurer de ne pas changer la valeur de $ NF
Gregory Patmore
Cela casse si vous essayez d'obtenir le troisième dernier champ commeawk -F '.' '{print $(NF-2)}'
gies0r
3
@Gurgeh: Cela se produit car il $(..)appelle une commande dans un sous-shell en fonction du shell que vous utilisez. Vous pouvez contourner ce problème en utilisant $ (NF-1)au lieu de $(NF-1).
mer du
21

Petit ajout à la réponse acceptée de Chris Kannon: n'imprimez que s'il y a réellement une avant-dernière colonne.

(
echo       | awk 'NF && NF-1 { print ( $(NF-1) ) }'
echo 1     | awk 'NF && NF-1 { print ( $(NF-1) ) }'
echo 1 2   | awk 'NF && NF-1 { print ( $(NF-1) ) }'
echo 1 2 3 | awk 'NF && NF-1 { print ( $(NF-1) ) }'
)
progz
la source
15

C'est le plus simple:

 awk '{print $--NF}' 

La raison pour laquelle l'original $NF--n'a pas fonctionné est que l'expression est évaluée avant la décrémentation, alors que ma décrémentation de préfixe est effectuée avant l'évaluation.

Steve
la source
En tant que mnémonique, ce comportement est le même que C / Java etc. int x = ++i int x = i++, le préfixe signifie incrémenter d'abord; postfix signifie incrémenter plus tard (affectation en premier).
Week
9
awk ' { print ( $(NF-1) ) }' file
ghostdog74
la source
4

Vous n'étiez pas loin du résultat! Cela le fait:

awk '{NF--; print $NF}' file

Cela décrémente le nombre de champs dans un, de sorte qu'il $NFcontient l'avant-dernier précédent.

Tester

Générons des nombres et imprimons-les sur des groupes de 5:

$ seq 12 | xargs -n5
1 2 3 4 5
6 7 8 9 10
11 12

Imprimons l'avant-dernier sur chaque ligne:

$ seq 12 | xargs -n5 | awk '{NF--; print $NF}'
4
9
11
fedorqui 'Alors arrêtez de nuire'
la source
3

Solution Perl similaire à la solution awk de Chris Kannon:

perl -lane 'print $F[$#F-1]' 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 @Ftableau. Par défaut, diviser sur les espaces

  • e exécuter le code perl

Le @Ftableau autosplit commence à l'index [0] tandis que les champs awk commencent par $ 1.
$#Fest le nombre d'éléments dans@F

Chris Koknat
la source
1
ou utilisez l'indexation négative déjà fournie par perl ...$F[-2]
Sundeep
2

Avez-vous essayé de démarrer de droite à gauche en utilisant la commande rev? Dans ce cas, il vous suffit d'imprimer la 2ème colonne:

seq 12 | xargs -n5 | rev | awk '{ print $2}' | rev
4
9
11
Fdv
la source
1

Décrémente d'abord la valeur, puis l'imprime -

awk ' { print $(--NF)}' file

OU

rev file|cut -d ' ' -f2|rev
VIPIN KUMAR
la source
0

Si vous avez de nombreuses colonnes et que vous souhaitez imprimer toutes les pages, mais pas les trois cloumns de la dernière, cela peut aider

awk '{ $NF="";$(NF-1)="";$(NF-2)="" ; print $0 }'

Sable1512
la source