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-- )  } '

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


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) ) }'
)

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.


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


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

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


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

1

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

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

OU

rev file|cut -d ' ' -f2|rev

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 }'

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.